如何允许实现使用自己的参数调用Mock(Moq)方法?

时间:2010-02-09 00:56:33

标签: .net unit-testing mocking moq

在测试使用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());

}

2 个答案:

答案 0 :(得分:2)

您可以使用It.IsAny<IMessage>()

像这样:

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

答案 1 :(得分:2)

在这种情况下,您可以使用It.Is<IMessage>期望匹配:

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

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