随机失败的 C# 单元测试
C# Unit test that fails randomly
我正在处理一个项目,该项目有一些单元测试在 Team City 上执行时随机失败。没有人可以在本地机器上重现相同的行为。
由于几乎所有测试都在 TestDelegate
操作内执行测试方法并在操作外执行 Asserts
和 Verifies
我认为这可能是并发问题。
但在我对测试代码进行任何更改之前,我想了解有关 .Net Framework 4.0.[= 中 TestDelegate
操作执行的更多信息18=]
这是一个随机失败的单元测试示例。
[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);
}
}
我的class方法
public override void MyMethod()
{
...DoALotOfStuff
AnyService.MockClassMethod();
}
这是 Team City 的错误
Expected invocation on the mock once, but was 0 times: _ => _.MockClassMethod()
No setups configured.
No invocations performed.
随机失败是什么原因?
是否可能仅在 Team City 的单独线程中执行该操作?
编辑:
我能够使用此命令执行测试随机失败。但是还是不知道为什么。
nunit3-console (ls -r ./tests/**/bin/**/*.Tests.dll -exclude *.Product* | % FullName | sort-object -Unique) --teamcity --x86 --framework=v4.0
您是否运行在您的测试中启用了任何 NUnit 的并行化选项?我在您的示例代码中没有看到任何并行化的证据,但它可以在其他地方启用——例如,在 AssemlyInfo.cs
.[=16= 的程序集级别可能有一个 [Parallelizable]
属性]
如果测试是 运行 并行进行的,您可能会在测试之间泄漏状态。 NUnit 为该夹具中的所有测试方法重复使用测试夹具的单个实例 (source)。由于您的模拟是固定范围的,因此两个测试的设置和断言逻辑之间可能存在竞争条件运行并发。
TestDelegate
本身对我来说并不重要。调用委托与调用任何其他方法没有太大区别,只是您是通过变量间接调用的。在您提供的示例代码中,_myClass.MyMethod()
仍将 运行 同步——除非您在别处引入了线程或并发。
编辑:
问题作者在评论中提供的其他信息,应他们的要求添加到此处以供查看:
After looking into the documentantion [https://github.com/nunit/docs/wiki/Console-Command-Line] I realized that nunit-console has a parameter --agents that is used to control running the assemblies in parallel and if not specified, all agent processes run tests at the same time, whatever the number of assemblies. When I added --agents=1 on the command line all tests run successfuly.
我正在处理一个项目,该项目有一些单元测试在 Team City 上执行时随机失败。没有人可以在本地机器上重现相同的行为。
由于几乎所有测试都在 TestDelegate
操作内执行测试方法并在操作外执行 Asserts
和 Verifies
我认为这可能是并发问题。
但在我对测试代码进行任何更改之前,我想了解有关 .Net Framework 4.0.[= 中 TestDelegate
操作执行的更多信息18=]
这是一个随机失败的单元测试示例。
[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);
}
}
我的class方法
public override void MyMethod()
{
...DoALotOfStuff
AnyService.MockClassMethod();
}
这是 Team City 的错误
Expected invocation on the mock once, but was 0 times: _ => _.MockClassMethod()
No setups configured.
No invocations performed.
随机失败是什么原因?
是否可能仅在 Team City 的单独线程中执行该操作?
编辑:
我能够使用此命令执行测试随机失败。但是还是不知道为什么。
nunit3-console (ls -r ./tests/**/bin/**/*.Tests.dll -exclude *.Product* | % FullName | sort-object -Unique) --teamcity --x86 --framework=v4.0
您是否运行在您的测试中启用了任何 NUnit 的并行化选项?我在您的示例代码中没有看到任何并行化的证据,但它可以在其他地方启用——例如,在 AssemlyInfo.cs
.[=16= 的程序集级别可能有一个 [Parallelizable]
属性]
如果测试是 运行 并行进行的,您可能会在测试之间泄漏状态。 NUnit 为该夹具中的所有测试方法重复使用测试夹具的单个实例 (source)。由于您的模拟是固定范围的,因此两个测试的设置和断言逻辑之间可能存在竞争条件运行并发。
TestDelegate
本身对我来说并不重要。调用委托与调用任何其他方法没有太大区别,只是您是通过变量间接调用的。在您提供的示例代码中,_myClass.MyMethod()
仍将 运行 同步——除非您在别处引入了线程或并发。
编辑:
问题作者在评论中提供的其他信息,应他们的要求添加到此处以供查看:
After looking into the documentantion [https://github.com/nunit/docs/wiki/Console-Command-Line] I realized that nunit-console has a parameter --agents that is used to control running the assemblies in parallel and if not specified, all agent processes run tests at the same time, whatever the number of assemblies. When I added --agents=1 on the command line all tests run successfuly.