随机失败的 C# 单元测试

C# Unit test that fails randomly

我正在处理一个项目,该项目有一些单元测试在 Team City 上执行时随机失败。没有人可以在本地机器上重现相同的行为。 由于几乎所有测试都在 TestDelegate 操作内执行测试方法并在操作外执行 AssertsVerifies 我认为这可能是并发问题。

但在我对测试代码进行任何更改之前,我想了解有关 .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.