【问题标题】:Unit tests and mocking for each test每个测试的单元测试和模拟
【发布时间】:2016-02-12 00:24:07
【问题描述】:

有时在我的测试中,我需要执行不同的 Setup() 调用,为每次测试运行设置不同的 Mocks - 如下所示:

private void Setup(bool isTrue)
{
    mock.Setup(x => x.DisplayNames).Returns(new Dictionary<int, string>());
    // ...
    // 5x more of these are the same for all tests

    if (isTrue)
      mock.Setup(x => x.DisplayOld).Returns(isTrue);
      // 5x more of these parameterlized setups 
      ...
}

现在,在我的每个单元测试中,我都会调用 Setup(true/false)。

由于单元测试是并行运行的(默认为 xUnit),这会导致任何锁定问题吗? (假设两个测试同时调用 Setup())。

如果是这样的话:

  1. 如何纠正这种情况?
  2. 如果一个人想要一个方法(如 setup())并传递一个参数 - 用于不同的模拟场景,那么正确的方法是什么?

【问题讨论】:

  • 如果您的Setup 方法被您的单元测试框架自动调用,那么是的,您会遇到问题。如果它实际上是由您的测试调用的,那么它应该没问题,假设 A)模拟对象没有被静态存储(例如,在对象工厂中),并且 B)模拟对象不是使用共享功能设置的(例如:.Returns(myDictionarySharedBetweenTests).
  • Rob,你能澄清一下吗?是的,我从我的每个测试 [Fact] 方法中调用 setup()。这是一个简单的设置,就像上面的代码一样 - 没有共享任何内容。基于 bool 标志的不同设置场景例如:mock.Setup(x => x.DoSomething).Returns(true) / false 等。

标签: c# .net unit-testing


【解决方案1】:

查看有关Test Context 模式的文章。您可以将模拟作为局部变量并在测试上下文类中自定义它们的设置。然后并行运行它们是安全的。我在 Java 中使用 JUnit+Mockito 以及在 .Net 中使用 NUnit/MSTest+Moq。

【讨论】:

  • 这仍然没有解决设置模拟(相同方式)10次并且根据参数仅设置1个模拟的问题。你最终得到 10 倍的 ctx.SomeMock.Setup()
  • 通常我在TestContext中有一个类似PerformDefaultSetup()的方法。这样我就不必在测试方法中重复相同的设置。
【解决方案2】:

您需要使用参数化单元测试。可以使用 xUnit 测试框架的 InlineData 属性。在这种情况下,不需要在 setup 方法中设置 mock。可在实际测试方法中直接设置。您的测试方法如下所示

[Theory]
[InlineData(false)]
[InlineData(true)]
public void SampleTest(bool flag)
{
    .... //do any set up operations
    .... //Assert logic to verify
}

测试框架将在运行时根据您通过 InlineData 属性提供的输入生成尽可能多的测试方法。由于测试方法在运行时被拆分为单独的方法,因此您不会遇到任何锁定或线程问题。

【讨论】:

  • 那不可行..我会有一堆重复的代码用于 10 倍起订量设置,只有一个会随参数而变化。
  • 仍有可能@ShaneKm。您可以在单独的方法中编写通用代码并从您的测试方法中调用该方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多