2009-04-07 4 views
18

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

[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(); 

} 

これは、そのパラメータのネタを取得するための多くの試みのちょうど最も最近のものである:

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); 
} 

は、ここでのテストです。参考までに、実際の値は初期状態から変更されません。

ターゲット呼び出しが失敗した後にAssert.AreEqual(expected、actual)を移動します。 .CallBackの代わりに.Verifiable()を追加し、ターゲットの後ろにremote.Verifyを呼び出すと(あるいは、厳密にモックを設定すると仮定します)、テストで提供するパラメータがコントローラメソッドで作成されたインスタンスと同じインスタンス。

私はMoq 3.0.308.2を使用しています。これをテストする方法に関するアイデアは高く評価されます。ありがとう!

答えて

19

私はあなたに正確な解決法を提供することはできませんが、パラメータの値を受け取り、RemotingHandlerに転送するアダプタの背後にあるpass-by-refセマンティクスを隠すこともできます。これは、模擬することが容易になり、インターフェイス(私は:-)常にREFパラメータの不審午前)

EDITからの「参照」いぼを削除します:

それとも、代わりにモックのスタブを使用することができます例えば:

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); 

をまた、あなたのコメントに言う:

私は、私はそれはあなたが設定する必要がまさに先例だと思う私は、より簡単に

テストを書くことができるように、バックエンドのランダムなビットを包むの先例を開始することを憎みます!あなたのコードがテスト可能でないなら、あなたはそれをテストするために苦労し続けます。テストを簡単にし、カバレッジを広げます。

+0

私はあなたがこのスタブをどのようにしているかわからないと思いますが(スタブについてはあまり知らないですが)。それがどのように扱われるかについて詳しく説明できますか? –

+0

また、私がrefの問題に同意するのと同じくらい、リモートレイヤが動作する方法であり、テストをより簡単に書くことができるように、バックエンドのランダムなビットをラップする前例を開始するのは嫌です。 –

+0

私は同様の問題を抱えていましたが、MoQの仕事をする上でゼロになってしまったので、私は自分のスタブを書くことができなかったことを忘れてしまいました!ありがとうございました。 –

9

残念ながら、私はMoqの直接のサポートなしにこれが可能であるとは確信していません。問題は、ラムダ式がrefまたはoutをサポートしていないことです。

「ラムダ式を直接REFをキャプチャしたり、囲んでいるメソッドからパラメータアウトすることはできません。」

http://msdn.microsoft.com/en-us/library/bb397687.aspx

あなたが仕事をしたい私も例を得ることができません。セットアップにrefを追加することはコンパイルに失敗します。

あなたはより多くの http://groups.google.com/group/moqdisc

幸運のための部品番号の議論をチェックアウトする場合があります。

+0

:) – Delashmate

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); 
+6

お返事ありがとうございます。私はクイックスタートでこれを見てきました(実際には、上司がMoqの最新バージョンにアップグレードすることを納得させました。残念ながら、この振る舞いは、(非常に不明瞭に)「呼び出しに対するref引数が同じインスタンスである場合にのみ一致します」に従っているようには見えません。 –

0

私は同様の問題に遭遇しました。私は最新のMoqを使って値を渡して解決策を得ました。

var instance = new Bar(); Mock.Setup(foo => foo.Submit(refインスタンス))。(true)を返します。

私も以前と同じ方法を使っていましたが、私は本当のように復帰していませんでした。

内部で実際の関数インスタンスが作成され、ユニットテストクラスから渡されたインスタンスを上書きすると問題が発生していました。私は実際のクラスの内部でインスタンスの作成を取り除き、それがうまくいった。

ご希望の場合はお手数ですが、

ありがとう

関連する問題