18

Moqに切り替えたところ、問題が発生しました。ビジネスオブジェクトの新しいインスタンスを作成し、ユーザー入力値からオブジェクトのプロパティを設定し、メソッド(SaveCustomerContact)を呼び出して新しいオブジェクトを保存するメソッドをテストしています。ビジネスオブジェクトはリモーティングレイヤーを通過するため、ref引数として渡されます。SaveCustomerContactに渡されるオブジェクトのすべてのプロパティが期待どおりに設定されていることをテストする必要がありますが、コントローラーメソッドで新しいものとしてインスタンス化されているため、そうすることができないようです。

public void AddContact() {

    var contact = new CustomerContact() { CustomerId = m_model.CustomerId };

    contact.Name = m_model.CustomerContactName;
    contact.PhoneNumber = m_model.PhoneNumber;
    contact.FaxNumber = m_model.FaxNumber;
    contact.Email = m_model.Email;
    contact.ReceiveInvoiceFlag = m_model.ReceiveInvoiceFlag;
    contact.ReceiveStatementFlag = m_model.ReceiveStatementFlag;
    contact.ReceiveContractFlag = m_model.ReceiveContractFlag;
    contact.EmailFlag = m_model.EmailFlag;
    contact.FaxFlag = m_model.FaxFlag;
    contact.PostalMailFlag = m_model.PostalMailFlag;
    contact.CustomerLocationId = m_model.CustomerLocationId;

    RemotingHandler.SaveCustomerContact( ref contact );
}

テストは次のとおりです。

[TestMethod()]
public void AddContactTest() {

    int customerId = 0;

    string name = "a";

    var actual = new CustomerContact();

    var expected = new CustomerContact() {
        CustomerId = customerId,
        Name = name
    };

    model.Setup( m => m.CustomerId ).Returns( customerId );
    model.SetupProperty( m => model.CustomerContactName, name );
    model.SetupProperty( m => m.PhoneNumber, string.Empty );
    model.SetupProperty( m => m.FaxNumber, string.Empty );
    model.SetupProperty( m => m.Email, string.Empty );
    model.SetupProperty( m => m.ReceiveInvoiceFlag, false );
    model.SetupProperty( m => m.ReceiveStatementFlag, false );
    model.SetupProperty( m => m.ReceiveContractFlag, false );
    model.SetupProperty( m => m.EmailFlag, false );
    model.SetupProperty( m => m.FaxFlag, false );
    model.SetupProperty( m => m.PostalMailFlag, false );
    model.SetupProperty( m => m.CustomerLocationId, 0 );

    remote
        .Setup( r => r.SaveCustomerContact( ref actual ) )
        .Callback( () => Assert.AreEqual( actual, expected ) );

    target.AddContact();

}

これは、そのパラメータを取得するための多くの試みの最新のものです。参考までに、actualの値は初期(構築)状態から変化しません。

ターゲット呼び出しが失敗した後、Assert.AreEqual(expected、actual)を移動します。.CallBackの代わりに.Verizable()をセットアップに追加してから、remote.Verifyを呼び出した場合、ターゲットの後で(または、モックをstrictに設定すると仮定して)、テストで提供するパラメーターがコントローラメソッドで作成されたものと同じインスタンス。

私はMoq3.0.308.2を使用しています。これをテストする方法についてのアイデアをいただければ幸いです。ありがとう!

4

4 に答える 4

19

正確な解決策を提供することはできませんが、別の方法として、パラメーターを値で受け取り、RemotingHandler に転送するアダプターの背後に参照渡しのセマンティクスを隠すこともできます。これはモックするのが簡単で、インターフェイスから「ref」いぼを削除します(私は常にrefパラメーターを疑っています:-))

編集:

または、モックの代わりにスタブを使用することもできます。次に例を示します。

public class StubRemotingHandler : IRemotingHandler
{
    public CustomerContact savedContact;

    public void SaveCustomerContact(ref CustomerContact contact)
    {
        savedContact = contact;
    }
}

テストで保存されたオブジェクトを調べることができます。

IRemotingHandler remote = new StubRemotingHandler();
...
//pass the stub to your object-under-test
...
target.AddContact();
Assert.AreEqual(expected, remote.savedContact);

また、コメントで次のように述べています。

テストをより簡単に記述できるように、バックエンドのランダムなビットをラップする前例を作りたくない

それはまさにあなたが設定する必要がある前例だと思います!コードがテスト可能でない場合、テストに苦労し続けることになります。テストを容易にし、カバレッジを増やします。

于 2009-04-07T17:33:51.680 に答える
10

Moq の最新バージョンは、このシナリオをサポートしています。

http://code.google.com/p/moq/wiki/QuickStartのクイックスタートから抜粋:

// ref arguments
var instance = new Bar();
// Only matches if the ref argument to the invocation is the same instance
mock.Setup(foo => foo.Submit(ref instance)).Returns(true);
于 2009-04-19T20:41:22.817 に答える