簡體   English   中英

當從匿名函數調用It.Is ...()時,為什么Moq設置/驗證匹配器失敗

[英]Why does Moq setup/verify matcher fail when It.Is…() is called from anonymous function

當嘗試簡化為與Moq匹配的Setup / Verify匹配創建相當復雜的表達式樹時,我遇到了一些奇怪的行為。

假設我在嘲笑下面定義的簡單接口

public interface IService
{
    int Send(int value);
}

以下代碼表示5個測試。 每個mockSender.Setup(...)一個測試。 任何人都可以解釋為什么標記為失敗的測試失敗了嗎?

[Test]
public void TestInlineSetup()
{
    const int expected = 5;
    var mockSender = new Mock<IService>(MockBehavior.Loose);

    //passes
    mockSender.Setup(s => s.Send(It.IsAny<int>())).Returns(expected);

    //fails
    var sendMatch = It.IsAny<int>();
    mockSender.Setup(s => s.Send(sendMatch)).Returns(expected);

    //passes
    mockSender.Setup(s => s.Send(SendMatchFromMethod())).Returns(expected);

    //fails
    var sendMatch = SendMatchFromMethod();
    mockSender.Setup(s => s.Send(sendMatch)).Returns(expected);

    //fails (this is somewhat contrived, but I have reasons for wanting to curry this)
    mockSender.Setup(s => s.Send(SendMatchFromCurriedMethod()())).Returns(expected);

    Assert.That(mockSender.Object.Send(expected), Is.EqualTo(expected));
}

public static int SendMatchFromMethod()
{
    return It.IsAny<int>();
}

public static Func<int> SendMatchFromCurriedMethod()
{
    return () => It.IsAny<int>();
}

編輯:我知道Mock.Of <..>(..)並且通常更喜歡使用它但在這種情況下它不是一個選項。

問題源於Moq嘗試解析提供的表達式樹以創建參數匹配器的方式。 你可以在這里找到來源: -

http://code.google.com/p/moq/source/browse/trunk/Source/MatcherFactory.cs

參考來源: -

  • 通過編譯和執行作為參數傳遞並查找任何匹配項的表達式來檢測It.IsAny<int>匹配器(請參閱此處 )。
  • 上述步驟僅用於方法調用和成員訪問

所以考慮到這一點....

  1. 第二次測試失敗,因為已在匹配器工廠之外評估了It.IsAny<int>方法。 因此,您將MemberAccess表達式設置為0。
  2. 第三次測試通過,因為SendMatchFromMethod被視為方法調用表達式,並且在MatcherFactory中計算調用。
  3. 第四次測試失敗的原因與第二次相同,函數已經評估過,而且Moq無法檢測到你實際上已經調用了它It.Is<Any>
  4. 第五次測試失敗,因為Expression被視為函數調用,而Moq不對此類表達式執行匹配器檢查。

說實話,第四個測試應該通過,它似乎是一個疏忽,它可能只是因為它有點邊緣情況。

最后, Match.Create<T>MatchAttribute可用於處理復雜謂詞,也許它們可能適合您的用例?

這似乎與我前一段時間遇到的情況非常相似: 使用It.IsAny <DateTime>()的Moq單元測試失敗

It.IsAny<int>()被評估時,問題似乎就出現了。 通過2次測試后,它將在Setup(...)內部進行評估,該工作正常。 在前兩個失敗的測試中,它的評估超出了Setup(...)的范圍,因此無法正確評估。 可能存儲在變量中的是It.IsAny<int>() ,它將是int0 )的默認值。

我不知道上次測試失敗的確切原因,但它可能是作為優化,您的靜態Func<int>Setup(...)執行之前得到評估,或者可能是它在之后得到評估Setup(...) ,但無論哪種方式都發生在Setup(...)

暫無
暫無

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

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