首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用Moq验证特定参数

使用Moq验证特定参数
EN

Stack Overflow用户
提问于 2011-02-10 20:19:11
回答 5查看 149.2K关注 0票数 213
代码语言:javascript
复制
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是否正确,但我仍然认为这不是正确的方法。

代码语言:javascript
复制
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());
}

顺便问一下,我如何从Verify调用中提取表达式?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-02-11 06:51:00

如果验证逻辑不是平凡的,那么编写一个大的lambda方法将会很混乱(如您的示例所示)。您可以将所有测试语句放在一个单独的方法中,但我不喜欢这样做,因为这会扰乱读取测试代码的流程。

另一种选择是在Setup调用中使用回调来存储传递给模拟方法的值,然后编写标准的Assert方法对其进行验证。例如:

代码语言:javascript
复制
// Arrange
MyObject saveObject;
mock.Setup(c => c.Method(It.IsAny<int>(), It.IsAny<MyObject>()))
        .Callback<int, MyObject>((i, obj) => saveObject = obj)
        .Returns("xyzzy");

// Act
// ...

// Assert
// Verify Method was called once only
mock.Verify(c => c.Method(It.IsAny<int>(), It.IsAny<MyObject>()), Times.Once());
// Assert about saveObject
Assert.That(saveObject.TheProperty, Is.EqualTo(2));
票数 311
EN

Stack Overflow用户

发布于 2011-02-10 22:53:50

我一直在以同样的方式验证调用-我相信这是正确的方法。

代码语言:javascript
复制
mockSomething.Verify(ms => ms.Method(
    It.IsAny<int>(), 
    It.Is<MyObject>(mo => mo.Id == 5 && mo.description == "test")
  ), Times.Once());

如果您的lambda表达式变得笨拙,您可以创建一个函数,该函数将MyObject作为输入并输出true/false...

代码语言:javascript
复制
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的一个bug,其中的错误消息指出该方法被多次调用,而根本没有调用。他们现在可能已经修复了这个问题--但是如果你看到这条消息,你可能会考虑验证这个方法是否被实际调用了。

EDIT:下面是一个多次调用verify的示例,用于验证是否为列表中的每个对象调用了一个函数(例如)。

代码语言:javascript
复制
foreach (var item in myList)
  mockRepository.Verify(mr => mr.Update(
    It.Is<MyObject>(i => i.Id == item.Id && i.LastUpdated == item.LastUpdated),
    Times.Once());

同样的设置方法...

代码语言:javascript
复制
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作为输入并返回内容的函数。

代码语言:javascript
复制
this.mockRepository
    .Setup(mr => mr.GetStuff(It.IsAny<int>()))
    .Returns((int id) => SomeFunctionThatReturnsStuff(id));

前段时间我在博客上看到的另一种方法(也许是Phil Haack?)让安装程序从某种出队对象返回-每次调用函数时,它都会从队列中拉出一个项目。

票数 154
EN

Stack Overflow用户

发布于 2017-02-24 07:44:27

一种更简单的方法是:

代码语言:javascript
复制
ObjectA.Verify(
    a => a.Execute(
        It.Is<Params>(p => p.Id == 7)
    )
);
票数 26
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4956974

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档