简体   繁体   中英

C# Unit test that fails randomly

I'm working on a project that has some unit test that fails randomly when executed on Team City. And nobody can reproduce the same behavior on local machines. As almost all tests executes the tested method inside a TestDelegate action and executes the Asserts and Verifies outside the actions I belive it could be a concurrency problem.

But before I do any change on test code I'd like to have more information about the execution of TestDelegate actions in .Net Framework 4.0 .

This is a example of a unit test that fails randomly.

[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);
    }
}

My class method

public override void MyMethod()
{
    ...DoALotOfStuff
    AnyService.MockClassMethod();
}   

This is the error on Team City

Expected invocation on the mock once, but was 0 times: _ => _.MockClassMethod()

No setups configured.

No invocations performed.

What could be the reason of it fails randomly?

Is possible that the action is executed in separate thread only on Team City?

EDIT:


I was able to do this test fail randomly using this command to execute the test. But still don't know why.

nunit3-console (ls -r ./tests/**/bin/**/*.Tests.dll -exclude *.Product* | % FullName | sort-object -Unique) --teamcity --x86 --framework=v4.0

Are you running your tests with any of NUnit's Parallelization options enabled? I don't see any evidence of parallelization in your example code, but it could be enabled elsewhere--for example, there could be a [Parallelizable] attribute at the assembly level in AssemlyInfo.cs .

If the tests are running in parallel, it's possible that you're leaking state between tests. NUnit re-uses a single instance of a test fixture for all test methods within that fixture ( source ). Since your mocks are are fixture-scoped, there could be a race condition between the setup and assertion logic of two tests running concurrently.

The TestDelegate itself doesn't look concerning to me. Calling a delegate isn't much different from calling any other method, except that you're doing it indirectly through a variable. In the example code you provided _myClass.MyMethod() will still run synchronously--unless you've introduced threading or concurrency elsewhere.

Edit:

Additional information provided from the question author in a comment, added here for visibility at their request:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM