繁体   English   中英

模拟动作 <T> 用NSubstitute

[英]Mocking Action<T> with 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签名简单地创建一个模拟并将其传递,生活将变得更加简单和可读。

随着David的评论(请参阅问题评论),我在这里发布实际上解决了我的问题的内容。

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

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

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);

然后将基本invoke方法更改为Virtual,以便替代方法可以覆盖它,例如,

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++);

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

如果您只想做一个间谍而不做任何外部跟踪变量(Rich Bryant的最佳答案是_counter ),则可以在替代项上使用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());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM