簡體   English   中英

使用Moq驗證參考參數的值

[英]Verify value of reference parameter with Moq

我剛剛切換到Moq並遇到了問題。 我正在測試一個創建業務對象的新實例的方法,從用戶輸入值設置對象的屬性,並調用方法(SaveCustomerContact)來保存新對象。 業務對象作為ref參數傳遞,因為它通過遠程處理層。 我需要測試傳遞給SaveCustomerContact的對象是否按預期設置了所有屬性,但因為它在控制器方法中被實例化為new,所以我似乎無法這樣做。

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

}

這只是獲得該參數的許多嘗試中最近的一次。 作為參考,實際值不會從其初始(構造)狀態改變。

在目標調用失敗后移動Assert.AreEqual(expected,actual)。 如果我將.Verifiable()添加到設置而不是.CallBack然后在目標之后調用remote.Verify(或者,我假設,將mock設置為strict)它總是失敗,因為我在測試中提供的參數不是與在控制器方法中創建的實例相同的實例。

我正在使用Moq 3.0.308.2。 關於如何測試這個的任何想法將不勝感激。 謝謝!

我無法為您提供精確的解決方案,但另一種方法是隱藏適配器后面的pass-by-ref語義,該適配器按值獲取參數並將其轉發給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);

你還在評論中說:

我不想開始包裝后端的隨機位的先例,所以我可以更容易地編寫測試

我認為這正是你需要設定的先例! 如果您的代碼不可測試,那么您將繼續努力測試它。 使測試更容易,並增加您的覆蓋范圍。

最新版本的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);

不幸的是,如果沒有Moq的直接支持,我不確定這是否可行。 問題是Lambda表達式不支持ref或out。

“lambda表達式不能直接從封閉方法中捕獲ref或out參數。”

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

我甚至無法得到像你這樣的例子來工作。 添加ref到設置無法編譯。

您可以查看Moq討論了解更多 http://groups.google.com/group/moqdisc

祝好運。

我遇到過類似的問題。 我通過使用最新的Moq並傳遞值來獲得解決方案

var instance = new Bar(); Mock.Setup(foo => foo.Submit(ref instance))。返回(true);

早些時候,我使用相同的方法,但我沒有得到真正的回報。

在實際的函數實例內部被創建並覆蓋從單元測試類傳遞的實例導致了問題。 我刪除了實際類中的實例創建,然后它工作了。

希望它會對你有所幫助。

謝謝

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM