Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何使用AutofacContrib.NSubstitute监视测试中的类_C#_Unit Testing_Nsubstitute_Automocking - Fatal编程技术网

C# 如何使用AutofacContrib.NSubstitute监视测试中的类

C# 如何使用AutofacContrib.NSubstitute监视测试中的类,c#,unit-testing,nsubstitute,automocking,C#,Unit Testing,Nsubstitute,Automocking,我正在使用NSpec框架、AutofacContrib.NSubstitute v3.3.2.0、NSubstitute v1.7.0.0(目前最新版本是1.8.2)在类库项目中运行单元测试 测试实例下的类是使用AutoSubstitute构建的,以便自动模拟所有需要的依赖项 AutoSubstitute autoSubstitute = new AutoSubstitute(); MainPanelViewModel viewModel = autoSubstitute.Resolve<

我正在使用NSpec框架、AutofacContrib.NSubstitute v3.3.2.0、NSubstitute v1.7.0.0(目前最新版本是1.8.2)在类库项目中运行单元测试

测试实例下的类是使用
AutoSubstitute
构建的,以便自动模拟所有需要的依赖项

AutoSubstitute autoSubstitute = new AutoSubstitute();

MainPanelViewModel viewModel = autoSubstitute.Resolve<MainPanelViewModel>();
因此,对于测试预期,我需要检查(spy)实例是否调用了基本方法:

viewModel.Received().ActivateItem(Arg.Any<SomeSpecificScreenType>());
viewModel.Received().ActivateItem(Arg.Any());
问题是:当我尝试这样做时,在运行时NSubstitute抱怨我只能对使用
Substitute.For()创建的对象运行
Received()
。我还快速检查了AutofacContrib.NSubstitute源代码,但我找不到一种方法来获取带有automocking的实例,同时以某种方式将其包装到spy对象或类似的东西中

我还认为,
Substitute.ForPartsOf()
可能会有所帮助,但在NSubstitute v1.7.0中似乎找不到这种方法

为完整起见,以下是NSSubstitute完整错误:

nssubstitute扩展方法(如.Received())只能对使用Substitute.For()和相关方法创建的对象调用


所以,实际问题并没有真正解决:只是问题本身消失了

为了检查行为是否正确,我回忆起我也可以从基类中使用
ActiveItem
公共属性,因此我停止使用
Receive()
,返回到简单的值比较

不过,为了将来的参考,我没有找到一种方法用这些库来监视被测试的类。我知道应该避免监视测试中的类,但与许多事情一样,有时您需要这样做


HTH

为了完整性,我做了一些实验,用
替换了NSubstitute的部分

ForPartsOf
的工作方式本质上是定义一个新的类,该类从用作模板的类继承。这就限制了模拟框架可以拦截的方法是定义为
abstract
virtual
的方法。如果要用自己的类从类继承,那么修改类的行为也会受到同样的限制

根据这些信息,让我们看看您的问题。您要拦截此呼叫:

base.ActivateItem(nextScreen);
因此,由于上述限制,为了能够拦截对
ActivateItem
的调用,必须在基类中将该方法标记为
virtual
。如果不是,那么在不更改应用程序结构的情况下,您将无能为力

如果该方法标记为
virtual
,则可以使用NSubstitute拦截它,但只能在调用NSubstitute实现时进行拦截。这是通过普通的方法分派来实现的,因为在调用虚拟方法时会调用它的最高级别实现(由NSubstitute提供的实现)。但是,当您通过
base
引用调用该方法时,它不起作用

所以,虽然你可以截取这个:

ActivateItem(nextScreen)
base.ActivateItem(nextScreen);
您无法截获此消息:

ActivateItem(nextScreen)
base.ActivateItem(nextScreen);
您在代码中使用
base.ActivateItem
的事实表明,您的被测类有自己的方法实现,您不想调用该方法,因此使用当前的工具无法实现您想要做的事情。这就是为什么你能找到一份工作是件好事


与大多数其他模拟框架处于相同的情况,包括。例外情况是,它使用一种完全不同的方式来拦截方法调用,这意味着它可以做其他框架无法做的事情。

您应该真正测试基类中
ActivateItem
的行为是否发生,而不是检查方法本身是否被调用(本质上是一个实施细节)。有什么原因你不能这样做吗?
substitute.ForPartsOf
可能会有帮助,但模拟你正在测试的类通常不是一个好主意。你想要测试的方法也需要是虚拟的,因此在不测试它的情况下,我怀疑显式调用
base.ActivateItem
是否会实际触发替换y、 测试该方法的功能可能更容易。我大体上完全同意这一点。我打算回答您的评论,即这是一个CaliburnMicro视图模型,鉴于我们进入UI视图领域,检查
ActivateItem
行为将很难。但我刚刚回忆起,还应该有一个
ActivateItem属性…所以现在我要检查一下!现在我想知道我是否应该结束这个问题,或者你可以发布一个自我回答,并在时间过去后接受它…大约24小时谢谢你的调查,我认为这对每个来到这个线程的人来说都是一个有用的澄清。只有2位:我知道te base.Xxxx只是为了清楚起见,在代码中,我只是调用
ActivateItem
,我没有覆盖它(尽管它是可覆盖的)。此外,在切换到NSubstitute之前,我使用Moq和Moq.AutoMock,并使用
mocker.CreateSelfMock()
成功地进行了监视,然后使用
Mock.Get(viewModel)。验证(vm=>vm.ActivateItem(It.IsAny())
@superjos有趣的是,是
base.Xxx
调用让它变得有趣。如果这只是一个普通的虚拟调用,那么你可以使用
Received
作为部分替换,正如你在问题中所说的那样,它应该可以正常工作。NSubstitute的发行说明可能有点错误,但它们似乎说,对于shoul的部分d在1.7.0版中…但是,再一次,被测试的类是由AutofacContrib.NSubstitute用automocking实例化的,我看不到它的任何方法可以返回部分替换