Moq - 独立执行时测试运行正常,但连续执行时失败

时间:2011-02-22 09:23:02

标签: c# unit-testing moq

我们正在使用Moq来执行一些单元测试,并且有一些奇怪的行为,也许这是我缺少的一些配置问题。
基本上,我有2个测试(调用一个Windows工作流,调用使用Invoke调用方法的自定义活动。我不知道这是否有帮助,但我想尽可能多地提供信息)。单独执行时测试运行正常,但是如果我在同一次运行中执行它们,第一个通过而第二个通过则失败(如果我改变它们的顺序无关紧要,第二个总是失败)

每次都会重新创建模拟,使用Unity加载。例如:

MockProcessConfigurator = MockFactory.Create<IProcessConfigurator>();
 MockProcessConfigurator.Setup(x => x.MyMethod(It.IsAny<Order>()));
[...]
InversionOfControl.Instance.Register<IProcessConfigurator>(MockProcessConfigurator .Object)

调用的调用(WF自定义活动)是

var invoker = new WorkflowInvoker(new MyWorkflow());
invoker.Invoke(inputParameter);

呼叫(调用呼叫)是

MyModuleService.ProcessConfigurator.MyMethod(inputOrder);

调试时,我发现ProcessConfigurator总是被模拟。

测试失败的调用就像这样简单:

MockEnvironment.MockProcessConfigurator.Verify(x => x.MyMethod(It.IsAny<Order>()), Times.Exactly(1));

调试时,实际上每次调用该方法,所以我怀疑模拟实例有一些问题。我在这里有点迷失,因为事情似乎得到了正确的实施,但出于某种原因,当它们一个接一个地运行时,就会出现问题

4 个答案:

答案 0 :(得分:1)

当两个测试共享某些内容时,通常会发生此类错误。

例如,您设置模拟时期望在测试设置中调用一次方法,然后两次测试每次调用该方法一次 - 您的期望将失败,因为它现在被调用了2次

这表明您应该将期望设置转移到每个测试中。

答案 1 :(得分:1)

针对此类问题的一般疑难解答是尝试在两次测试之间隔离依赖

  1. 将任何设置代码移至测试内部。
  2. 将任何拆解代码移至测试内部。
  3. 将任何字段初始值设定项移至测试内部。 (每个夹具只运行一次!)
  4. 这应该使你的测试在一起运行时通过。当您获得绿灯时,您可以再次开始将重复的内容移出到初始化器/设置一件,并在每次更改后运行测试。

    您应该能够了解导致测试之间这种耦合的原因。祝你好运!

答案 2 :(得分:0)

要扩展Sohnee给出的答案,我会检查我的设置/拆解方法,以确保您正确整理所有内容。我在批量运行测试时没遇到类似的问题而没有整理我的模拟对象。

答案 3 :(得分:0)

我不知道这是否相关,但MockFactory.Create似乎很奇怪。我通常按​​如下方式创建模拟:

var mockProcessConfigurator = new Mock<IProcessConfigurator>();

当使用MockFactory(我从未需要)时,通常会创建一个它的实例。来自moq QuickStart

var factory = new MockFactory(MockBehavior.Strict) { DefaultValue = DefaultValue.Mock };

在MockFactory上调用静态方法似乎打败了目的。如果你有一个非标准的命名约定,其中MockFactory实际上是MockFactory类型的变量,那可能不是你的问题(但将是一个混乱的常见来源)。如果MockFactory是您的测试类的属性,请确保它在SetUp上重新创建。

如果可能的话,我会取消工厂,因为它是共享国家的潜在来源。

编辑:另外,WorkflowInvoker.Invoke将Activity作为参数。您可以只传递自定义活动的实例,而不是创建整个工作流来测试自定义活动。如果这是您想要测试的内容,它会使您的单元测试更加集中。