使用NSubstitute </t>模拟行动<t>

时间:2015-03-27 12:19:27

标签: c# wcf nsubstitute

Web服务的代理需要单元测试,而不是 - 显然 - 访问Web服务。

这是我喜欢中性的方法 -

public void Invoke(Action<T> action)
{
    Task.Run(async ()=> { await _invoker.Invoke(this, action); }).Wait();
}

有没有办法使用NSubstitute模拟Action参数?我一直在使用

_proxy.When(x => x.Invoke($args_go_here)).Do(x => _counter++);

但是我在制定Args表达方式时遇到了麻烦。如果我可以简单地创建一个带有Action签名的模拟并将其传入,那么生活会更简单,更易读。

2 个答案:

答案 0 :(得分:2)

正如大卫的建议(见问题评论),我在这里发布了实际解决我问题的内容。

问题在于测试调用WCF服务的代码实际上是在运行,发送正确的东西等等。我非常强烈地建议任何沿着这条路线行进的人都是TDD风格的,因为改装单元测试的是其他人的#39 ;工作代码不是一种愉快的经历。

在这种情况下,代理不是自动生成的,而是从单个ProxyBase类继承而来,该类暴露了上面引用的Invoke(Action操作)方法。

public void Invoke(Action<T> action)
{
    Task.Run(async ()=> { await _invoker.Invoke(this, action); }).Wait();
}

我的第一个想法是模拟Action(我最终这样做了)但是这非常正确地产生了Service Not Found错误。

最终,我最终获得了(特定)Proxy Invoker类的NSubstitute Automock,它是通过实际将依赖项传递给构造函数而创建的 -

var myProxyMock = Substitute.For<MyProxy>(dependency1, dependency2);

并将基本调用方法更改为虚拟,以便替换可以覆盖它,如此 -

public virtual void Invoke(Action<T> action)
{
    Task.Run(async ()=> { await _invoker.Invoke(this, action); }).Wait();
}

现在,通过替换Action,我实际上可以有效地测试周围的代码。

var actionSubstitute = Substitute.For<Action<MyService>>();

并应用相关的返回值,natch。

最后,我们有 -

myProxyMock.When(x => x.Invoke(Arg.Any<Action<MyService>>).Do(x => _counter++);

问题解决了。非常感谢,大卫。

答案 1 :(得分:1)

如果您只想做一个间谍而不做外部跟踪变量(_counter是Rich Bryant的最佳答案),则可以在替代品上使用ReceivedCalls()。下面的示例使用System.Linq

var myAction = Substitute.For<Action<string>>();
myAction.Invoke("abc");

// assert the Action<string> was called once
Assert.Equal(1, myAction.ReceivedCalls().Count());

// assert that the first parameter on the first call was "abc"
Assert.Equal("abc", myAction.ReceivedCalls().First().GetArguments().First());