Deadlock on xUnit Test when Processing Data on Database

Viewed 1442

So I have two classes, each consists of database integration tests. In each classes' constructor I put a method to reset the database:

public class FirstClassSpec {
    public FirstClassSpec() {
        var dataSetup = new DataSetup();
        dataSetup.CleanTables();
    }

    [Fact]
    public async Task FirstTest() {
        using(var conn = new SqlConnection("connStringHere")){
            var result = await conn.ExecuteAsync("someSqlCommand");
            Assert.True(result > 0);
        }
    }
}

public class SecondClassSpec {
    public SecondClassSpec() {
        var dataSetup = new DataSetup();
        dataSetup.CleanTables();
    }

    [Fact]
    public async Task SecondTest() {
        using(var conn = new SqlConnection("connStringHere")){
            var result = await conn.ExecuteAsync("someSqlCommand");
            Assert.True(result > 0);
        }
    }
}

public class DataSetup {
    public void CleanTables() {
        using(var conn = new SqlConnection("connStringHere")){
            await conn.Execute("someSqlCommandToCleanTables");
        }
    }
}

In order to run the tests Visual Studio 2015, I use Run All Tests in Test Explorer. I got the message of

Transaction (Process ID {someID}) was deadlocked on lock resources with another process

This problem only happens if I run all of the tests. If I run each tests one by one or running many tests but from the same class, the deadlock never occurs. I found out that the CleanTables() method which is called in the classes' constructor cause this. I assume the tests run in parallel, and CleanTables() was called on the same time by the two classes. So then I tried to make CleanTables() into an async method:

public async Task<int> CleanTables() {
    using(var conn = new SqlConnection("connStringHere")){
        return await conn.Execute("someSqlCommandToCleanTables");
    }
}

And then on the classes' constructor I call it like this:

public FirstClassSpec() {
    var dataSetup = new DataSetup();
    dataSetup.CleanTables().Wait();
}

public SecondClassSpec() {
    var dataSetup = new DataSetup();
    dataSetup.CleanTables().Wait();
}

But now when I try to Run All Tests, the tests were running but they never get done and I never get the result.

My question is, why the deadlock occurs? and why changing the CleanTables() method into async made the running tests never get done? I really need to clean the tables before each tests run.

----------------- UPDATE -----------------------

I've tried decorated all of the test classes with [Collection["CollectionName"]], with each classes has different name:

[Collection["FirstSpec"]]
public class FirstClassSpec {
    //....
}

[Collection["SecondSpec"]]
public class FirstClassSpec {
    //....
}

But the deadlock still occurs..

----------------- UPDATE 2 -----------------------

Turns out classes which have the same collection name would be executed sequentially and this solves the deadlock problem.

1 Answers
Related