我正在开发一个项目,该项目具有一些在Team City上执行时会随机失败的单元测试。而且没有人可以在本地计算机上重现相同的行为。
由于几乎所有测试都在TestDelegate
动作中执行被测试的方法,并在我相信的动作之外执行Asserts
和Verifies
,因此可能是并发问题。
但是在对测试代码进行任何更改之前,我想了解有关在 .Net Framework 4.0 中执行TestDelegate
操作的更多信息。
这是单元测试随机失败的示例。
[TestFixture]
public class MyClassTest
{
private Mock<IAnyService> _anyService;
private MyClass _myClass;
[SetUp]
public void Setup()
{
_anyService = new Mock<IAnyService>();
_myClass.AnyService = new MyClass() { AnyService = _anyService.Object };
}
[Test]
public void MyClass_Should_Call_MockClassMethod()
{
TestDelegate action = () => _myClass.MyMethod();
Assert.DoesNotThrow(action);
_anyService.Verify(_ => _.MockClassMethod(), Times.Once);
}
}
我的课堂方法
public override void MyMethod()
{
...DoALotOfStuff
AnyService.MockClassMethod();
}
这是Team City上的错误
预期对该模拟调用一次,但被调用0次:_ => _.MockClassMethod()
未配置任何设置。
未执行任何调用。
它随机失败的原因是什么?
是否有可能仅在Team City上以单独的线程执行操作?
编辑:
我能够使用此命令执行测试以使测试随机失败。但还是不知道为什么。
nunit3-console (ls -r ./tests/**/bin/**/*.Tests.dll -exclude *.Product* | % FullName | sort-object -Unique) --teamcity --x86 --framework=v4.0
答案 0 :(得分:2)
您是否在启用NUnit的任何Parallelization选项的情况下运行测试?我在您的示例代码中没有看到任何并行化的迹象,但是可以在其他地方启用它-例如,在[Parallelizable]
的程序集级别可能有一个AssemlyInfo.cs
属性。
如果测试并行运行,则可能在测试之间泄漏状态。 NUnit将一个测试治具的单个实例重新用于该治具(source)中的所有测试方法。由于您的模拟是固定的,因此在同时运行的两个测试的设置和断言逻辑之间可能存在竞争条件。
TestDelegate
本身与我无关。调用委托与调用任何其他方法没有什么不同,除了通过变量间接地进行。在示例代码中,您提供的_myClass.MyMethod()
仍将同步运行,除非您在其他地方引入了线程或并发。
编辑:
问题作者在评论中提供的其他信息,请在此处添加以供他们查看:
在研究了文档后[github.com/nunit/docs/wiki/Console-Command-Line],我意识到nunit-console有一个参数--agents,用于控制并行运行程序集,如果没有的话如果指定,则无论程序集数量如何,所有代理程序进程都将同时运行测试。当我在命令行上添加--agents = 1时,所有测试都成功运行。