[c#] 用Moq驗證具體參數



1 Answers

我一直在以同樣的方式驗證電話 - 我相信這是正確的方式。

mockSomething.Verify(ms => ms.Method(
    It.IsAny<int>(), 
    It.Is<MyObject>(mo => mo.Id == 5 && mo.description == "test")
  ), Times.Once());

如果您的lambda表達式變得笨拙,您可以創建一個函數,將MyObject作為輸入並輸出true / false ...

mockSomething.Verify(ms => ms.Method(
    It.IsAny<int>(), 
    It.Is<MyObject>(mo => MyObjectFunc(mo))
  ), Times.Once());

private bool MyObjectFunc(MyObject myObject)
{
  return myObject.Id == 5 && myObject.description == "test";
}

此外,請注意Mock中的錯誤,其中錯誤消息指出該方法在完全未被調用時被多次調用。 他們現在可能已經修復了這個問題 - 但是如果你看到這個信息,你可能會考慮驗證這個方法實際上是被調用的。

編輯:下面是一個示例調用驗證多次的情況下,您要驗證您調用列表中的每個對象的函數(例如)。

foreach (var item in myList)
  mockRepository.Verify(mr => mr.Update(
    It.Is<MyObject>(i => i.Id == item.Id && i.LastUpdated == item.LastUpdated),
    Times.Once());

同樣的設置方法...

foreach (var item in myList) {
  var stuff = ... // some result specific to the item
  this.mockRepository
    .Setup(mr => mr.GetStuff(item.itemId))
    .Returns(stuff);
}

所以每次為該itemId調用GetStuff時,它都會返回特定於該項目的東西。 或者,您可以使用一個將itemId作為輸入並返回內容的函數。

this.mockRepository
    .Setup(mr => mr.GetStuff(It.IsAny<int>()))
    .Returns((int id) => SomeFunctionThatReturnsStuff(id));

有一段時間我在博客上看到的另一種方法(菲爾哈克也許?)已經從某種出列對象返回了設置 - 每次函數被調用時它都會從隊列中拉出一個項目。

Question
public void SubmitMessagesToQueue_OneMessage_SubmitSuccessfully()
{
    var messageServiceClientMock = new Mock<IMessageServiceClient>();
    var queueableMessage = CreateSingleQueueableMessage();
    var message = queueableMessage[0];
    var xml = QueueableMessageAsXml(queueableMessage);
    messageServiceClientMock.Setup(proxy => proxy.SubmitMessage(xml)).Verifiable();
    //messageServiceClientMock.Setup(proxy => proxy.SubmitMessage(It.IsAny<XmlElement>())).Verifiable();

    var serviceProxyFactoryStub = new Mock<IMessageServiceClientFactory>();
    serviceProxyFactoryStub.Setup(proxyFactory => proxyFactory.CreateProxy()).Returns(essageServiceClientMock.Object);
    var loggerStub = new Mock<ILogger>();

    var client = new MessageClient(serviceProxyFactoryStub.Object, loggerStub.Object);
    client.SubmitMessagesToQueue(new List<IMessageRequestDTO> {message});

    //messageServiceClientMock.Verify(proxy => proxy.SubmitMessage(xml), Times.Once());
    messageServiceClientMock.Verify();
}

我開始使用Moq並掙扎了一下。 我試圖驗證messageServiceClient正在接收正確的參數,這是一個XmlElement,但我找不到任何方式使其工作。 它只有在我沒有檢查特定值時才有效。

有任何想法嗎?

部分答案:我找到了一種方法來測試發送給代理的xml是否正確,但我仍然認為這不是正確的方法。

public void SubmitMessagesToQueue_OneMessage_SubmitSuccessfully()
{
    var messageServiceClientMock = new Mock<IMessageServiceClient>();
    messageServiceClientMock.Setup(proxy => proxy.SubmitMessage(It.IsAny<XmlElement>())).Verifiable();
    var serviceProxyFactoryStub = new Mock<IMessageServiceClientFactory>();
    serviceProxyFactoryStub.Setup(proxyFactory => proxyFactory.CreateProxy()).Returns(messageServiceClientMock.Object);
    var loggerStub = new Mock<ILogger>();

    var client = new MessageClient(serviceProxyFactoryStub.Object, loggerStub.Object);
    var message = CreateMessage();
    client.SubmitMessagesToQueue(new List<IMessageRequestDTO> {message});

    messageServiceClientMock.Verify(proxy => proxy.SubmitMessage(It.Is<XmlElement>(xmlElement => XMLDeserializer<QueueableMessage>.Deserialize(xmlElement).Messages.Contains(message))), Times.Once());
}

順便說一句,我如何從驗證呼叫中提取表達式?




我相信Moq會檢查平等的問題。 而且,由於XmlElement不會覆蓋Equals,因此它的實現將檢查引用是否相等。

你不能使用自定義對象,所以你可以重寫equals?




Related