如何允许实现使用自己的参数调用 Mock (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());
}
When testing a class that uses a Moq dependency, I'd like the class to supply the arguments to a Moq method, rather than creating the arguments myself in the test case.
I have an interface, that has one method, which takes one argument.
public interface IMessageForwardProxy
{
IMessage Send(IMessage request);
}
I have a class that calls this method with a number of different arguments depending on the method called on the class. For instance:
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;
}
}
Now as you can see, the Messenger class is responsible for creating the arguments that are passed to the Send method of the interface. When I'm testing this Messenger class, I would like to Mock the IMessageForwardProxy's Send method, without providing the argument in my tests. I see providing the argument as coupling my tests to the implementation (and duplicating work).
If I want to test the DeliverSomeOtherMessage method on the Messenger class, how would I mock the 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());
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用
It.IsAny()
像这样:
You can use
It.IsAny<IMessage>()
Like this:
在这种情况下,您可以使用
It.Is
期望匹配:仅当传递给 It.Is 方法的 preducate 计算结果为 true 时,此匹配才为 true,因此此 Setup 和相应的返回值仅当您调用 DeliverSomeOtherMessage 方法时才会使用。
In this case, you can use the
It.Is<IMessage>
expectation match:This match is only true when the preducate passed to the It.Is method evaluates to true, so this Setup and corresponding return value will only be used when you invoke the DeliverSomeOtherMessage method.