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签名的模拟并将其传入,那么生活会更简单,更易读。
答案 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());