2010-07-17 46 views
107

想象一下这个类起订量:怎么到传递给嘲笑服务的方法的参数

public class Foo { 

    private Handler _h; 

    public Foo(Handler h) 
    { 
     _h = h; 
    } 

    public void Bar(int i) 
    { 
     _h.AsyncHandle(CalcOn(i)); 
    } 

    private SomeResponse CalcOn(int i) 
    { 
     ...; 
    } 
} 

莫(Q)他妈的处理器Foo中的一个测试,我怎么就能够检查什么Bar()已经传递到_h.AsyncHandle

+0

你的意思是“AsyncHandle”(多余的“n”)?你可以发布处理程序的代码,或者如果它是标准类型,则指定完全限定类型名称? – TrueWill 2010-07-17 01:23:13

+0

你能展示你的骨架测试来展示你的想法吗?虽然我明白,从我们这边来看,很显然,从我们这边来看,似乎有人没有花时间在没有做出长期推测性答案的情况下提出问题。 – 2010-07-19 10:12:37

+1

既没有Foo也没有酒吧()也没有这样的东西。这只是一些演示代码,可以显示我所处的情况,而不会分散您的具体应用。我得到了答案,我希望得到。 – Jan 2010-07-21 21:07:06

回答

178

可以使用Mock.Callback法:

var mock = new Mock<Handler>(); 
SomeResponse result = null; 
mock.Setup(h => h.AnsyncHandle(It.IsAny<SomeResponse>())) 
    .Callback<SomeResponse>(r => result = r); 

// do your test 
new Foo(mock.Object).Bar(22); 
Assert.NotNull(result); 

如果你只是要检查的东西在参数传递的简单,你也可以直接做到这一点:

mock.Setup(h => h.AnsyncHandle(It.Is<SomeResponse>(response => response != null))); 
+1

完美,谢谢! – Jan 2010-07-21 21:04:58

+14

一个方面,如果你的函数有多个参数,你需要在通用的'Callback <>()'Moq方法中指定所有的类型。例如,如果你的方法定义了'Handler.AnsyncHandle(string,SomeResponse)',你需要'/ * ... * /。回调(r => result = r);'。我还没有在很多地方发现这个明确表示,所以我想我会在这里添加它。 – 2016-08-31 19:29:00

17

Gamlor的答案的作品,但另一种做法(我认为在测试中更具表现力的一种方法)是...

var mock = new Mock<Handler>(); 
var desiredParam = 47; // this is what you want to be passed to AsyncHandle 
new Foo(mock.Object).Bar(22); 
mock.Verify(h => h.AsyncHandle(desiredParam), Times.Once()); 

验证功能非常强大,值得花时间去习惯。

+9

如果你只是想检查一个方法是否被一个已知参数调用,那么这种方法很好。如果在编写测试时尚未创建参数(例如,所讨论的单元在内部创建参数),则回调使您可以捕获和询问此问题,而您的方法则不然。 – Michael 2014-02-25 14:17:01

+0

我需要存储传递的值,因为我需要验证传递的所有对象的集合。 – MrFox 2016-09-26 12:47:30

1

您可以使用It.Is<TValue>()匹配器。

var mock = new Mock<Handler>(); new Foo(mock.Object).Bar(22); mock.Verify(h => h.AsyncHandle(It.Is<SomeResponse>(r => r != null)));

+0

Typo - 'AnsyncHandle'应该是'AsyncHandle' – 2017-10-31 16:19:30

2

Gamlor的回答为我工作,但我想我会扩大约翰木匠的评论,因为我一直在寻找,涉及多个参数的解决方案。我想其他人偶然遇到这个页面可能会遇到类似的情况。我在Moq documentation中找到了此信息。

我将使用Gamlor的示例,但假设AsyncHandle方法有两个参数:一个string和一个SomeResponse对象。

var mock = new Mock<Handler>(); 
string stringResult = string.Empty; 
SomeResponse someResponse = null; 
mock.Setup(h => h.AsyncHandle(It.IsAny<string>(), It.IsAny<SomeResponse>())) 
    .Callback<string, SomeResponse>((s, r) => 
    { 
     stringResult = s; 
     someResponse = r; 
    }); 

// do your test 
new Foo(mock.Object).Bar(22); 
Assert.AreEqual("expected string", stringResult); 
Assert.IsNotNull(someResponse); 

基本上你只需要添加另一It.IsAny<>()与适当的类型,添加另一种类型至Callback方法,并改变lambda表达式适当。