简体   繁体   English

模拟动作 <T> 用NSubstitute

[英]Mocking Action<T> with NSubstitute

A proxy for a webservice needs unit testing without - obviously - hitting the web service. Web服务的代理需要进行单元测试,而不会(显然)击中Web服务。

This is the method I'd like to neuter - 这是我想绝育的方法-

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

Is there any way to mock the Action parameter using NSubstitute? 有什么方法可以使用NSubstitute模拟Action参数吗? I've been working along the lines of using 我一直在努力使用

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

but I'm having real troubles formulating the Args expressions. 但是我在编写Args表达式时遇到了麻烦。 If I could simply create a mock with the Action signature and pass it in, life would be much simpler and more readable. 如果我可以使用Action签名简单地创建一个模拟并将其传递,生活将变得更加简单和可读。

As David recomments (see comments on question), I'm posting what actually solved my issue here. 随着David的评论(请参阅问题评论),我在这里发布实际上解决了我的问题的内容。

The problem was testing that the code to call WCF services was actually running, sending the right stuff, etc. I would VERY STRONGLY recommend that anyone going down this route do so in TDD style as retrofitting unit tests over somebody else's working code is not an enjoyable experience. 问题是测试调用WCF服务的代码是否正在实际运行,发送正确的东西等。我非常强烈地建议任何沿着这条路线走的人都以TDD风格这样做,因为对其他人的工作代码进行单元测试改型不是愉快的经历。

In this case, proxies were not autogenerated but inherited from a single ProxyBase class which exposed the Invoke(Action action) method referenced above. 在这种情况下,代理不会自动生成,而是从暴露了上面引用的Invoke(Action action)方法的单个ProxyBase类继承而来。

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

My first thought was to mock Action (and I did end up doing so) but this produced Service Not Found errors, quite correctly. 我的第一个想法是模拟Action(最终确实这样做了),但这确实产生了Service Not Found错误。

Eventually I ended up with an NSubstitute Automock of the (specific) Proxy Invoker class, created by actually passing dependencies into the constructor like so - 最终,我得到了(特定的)Proxy Invoker类的NSubstitute Automock,它是通过将依赖项实际上传递给构造函数而创建的,如下所示:

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

and changing the base invoke method to a Virtual so that the substitute could override it, like so - 然后将基本invoke方法更改为Virtual,以便替代方法可以覆盖它,例如,

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

Now, by substituting Action, I could actually test the surrounding code efficiently. 现在,通过替换Action,我实际上可以有效地测试周围的代码。

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

and apply relevant return values, natch. 并应用相关的返回值,natch。

so eventuially, we have - 所以最终,我们有-

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

Problem solved. 问题解决了。 Many thanks, David. 非常感谢,大卫。

If you just want a spy without making an external tracking variable, (what _counter is in Rich Bryant's great answer), it's possible to use ReceivedCalls() on the substitute. 如果您只想做一个间谍而不做任何外部跟踪变量(Rich Bryant的最佳答案是_counter ),则可以在替代项上使用ReceivedCalls() Below example uses System.Linq : 下面的示例使用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