0

所以我有两个类,每个类都包含数据库集成测试。在每一个类的构造函数,我把一个方法来重置数据库:处理数据库上的数据时xUnit测试的死锁

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

为了运行测试的Visual Studio 2015年,我在Test Explorer使用Run All Tests。我

事务(进程ID {} someID)的消息被死锁在锁资源 与另一个进程

如果我运行所有测试中才会出现这种问题。如果我逐个运行每个测试,或者运行多个测试,但是从同一个类中运行,则永远不会发生死锁。 我发现在类的构造函数中调用的CleanTables()方法会导致此问题。我假设测试并行运行,并且两个类同时调用CleanTables()。 于是我试图让CleanTables()成异步方法:

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

,然后在类的构造函数我这样称呼它:

但现在当我尝试Run All Tests,测试正在运行,但他们从来没有完成,我从来没有得到结果。

我的问题是,为什么发生死锁?以及为什么将CleanTables()方法更改为async使运行测试永远无法完成?我真的需要在每次测试运行前清理表格。

-----------------更新-----------------------

我已经试过所有的装饰测试类与[Collection["CollectionName"]],每个类都有不同的名称:

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

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

但僵局仍然存在..

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

原来具有相同集合名称的类将按顺序执行并解决死锁问题。

+0

您是否尝试过使用[SQL Server事件探查到分析僵局(https://docs.microsoft.com/ EN-US/SQL /工具/ SQL服务器廓/分析,死锁,与-SQL服务器分析器)?它在过去帮助过我。 –

回答

1

您的猜测对于并行运行的测试是正确的。默认情况下,xUnit不会同时在同一个类中运行测试。所以要解决您的问题,您可以将所有测试移到一个类中。或者,您可以用[Collection("My Collection")]来修饰您的课程,以表明两个课程中的测试不应该并行运行。

您可以了解更多有关如何的xUnit决定如何并行运行测试这里:https://xunit.github.io/docs/running-tests-in-parallel.html

+0

感谢您的解决方案!但是,不,我不想把所有的测试都移到一个班级(这将变得很难维护)。今天晚些时候我会试着用'[Collection [“My Collection”]]来装饰我的课程。如果这是工作,我会标记你的答案作为答案! :) – samAlvin

+0

我试过用[集合[“CollectionName”]]装饰所有测试类,每个类都有不同的名称..但是仍然发生死锁..我更新了我的问题。 – samAlvin

+0

每个类都应该具有相同的集合名称。 –