【问题标题】:How do I allow an implementation to call a Mock (Moq) method with its own arguments?如何允许实现使用自己的参数调用 Mock (Moq) 方法?
【发布时间】:2010-02-09 00:56:32
【问题描述】:

在测试使用 Moq 依赖项的类时,我希望该类为 Moq 方法提供参数,而不是自己在测试用例中创建参数。

我有一个接口,它有一个方法,它接受一个参数。

public interface IMessageForwardProxy
{
    IMessage Send(IMessage request);
}

我有一个类,它使用许多不同的参数调用此方法,具体取决于类上调用的方法。例如:

public class Messenger 
{
    private IMessageForwardProxy _link;

    public Messenger(IMessageForwardProxy proxy) { _link = proxy; }

    public bool DeliverSomeMessage() {
        IMessage m1 = new MessageOne();
        var response = _link.Send(m1);
        return response.Succeeded;
    }

    public bool DeliverSomeOtherMessage() {
        IMessage m2 = new MessageTwo();
        var response = _link.Send(m2);
        return response.Succeeded;
    }
}

现在您可以看到,Messenger 类负责创建传递给接口的 Send 方法的参数。当我测试这个 Messenger 类时,我想模拟 IMessageForwardProxy 的 Send 方法,而不在我的测试中提供参数。我认为提供参数是为了将我的测试与实现耦合(并重复工作)。

如果我想在 Messenger 类上测试 DeliverSomeOtherMessage 方法,我将如何模拟 IMessageForwardProxy?

[Test]
public void TestDeliverSomeOtherMessage() {
    var mockProxy = new Mock<IMessageForwardProxy>();

    // This is what I want to avoid, since the method I'm testing creates this argument
    IMessage m2 = new MessageTwo(); 
    mockProxy.Setup(m => m.Send(m2)).Returns(new ReturnMessageTwo());

    // Can I do something like this instead? Define the signature, but not the param?
    mockProxy.Setup(m => m.Send(typeof(IMessage))).Returns(new ReturnMessageTwo());

    var messenger = new Messenger(mockProxy.Object);
    Assert.True(messenger.DeliverSomeOtherMessage());

}

【问题讨论】:

    标签: .net unit-testing mocking moq


    【解决方案1】:

    您可以使用It.IsAny&lt;IMessage&gt;()

    像这样:

    mockProxy.Setup(m => m.Send(It.IsAny<IMessage>())).Returns(new ReturnMessageTwo());
    

    【讨论】:

      【解决方案2】:

      在这种情况下,您可以使用It.Is&lt;IMessage&gt; 期望匹配:

      mockProxy.Setup(m => m.Send(It.Is<IMessage>(m => m is MessageTwo)))
          .Returns(new ReturnMessageTwo());
      

      仅当传递给 It.Is 方法的谓词计算结果为 true 时,此匹配才为 true,因此仅当您调用 DeliverSomeOtherMessage 方法时才会使用此 Setup 和相应的返回值。

      【讨论】:

      • 那不是和It.IsAny&lt;MessageTwo&gt;()一样吗?
      • @Jeff Cyr:不,因为那会匹配带有签名 Send(MessageTwo) 的方法,而该方法不存在。
      猜你喜欢
      • 2011-11-25
      • 2016-02-22
      • 2012-03-29
      • 1970-01-01
      • 2011-01-12
      • 2017-05-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多