xUnit测试死锁

xUnit test deadlock

当我 运行 我的 xUnit 单元测试时,我有时会在一项或多项测试中收到类似 "Transaction (Process ID 58) was deadlocked on lock resources with another process and has been chosen as the deadlock victim" 的错误消息,似乎是随机的。如果我自己重新运行任何失败的测试,它就会通过。

我应该怎么做才能防止这种情况发生?是否可以选择 运行 一个接一个地而不是一次全部地进行测试?

(N.B。我正在 运行 在 Visual Studio 2015 下 ASP.Net 5 MVC 控制器中对 API 方法进行测试)

这是我偶尔失败的测试之一的示例:

[Fact]
private void TestREAD()
{
    Linq2SQLTestHelpers.SQLCommands.AddCollections(TestCollections.Select(collection => Convert.Collection2DB(collection)).ToList(), TestSettings.LocalConnectionString);
    foreach (var testCollection in TestCollections)
    {
        var testCollectionFromDB = CollectionsController.Get(testCollection.Id);
        Assert.Equal(testCollection.Description, testCollectionFromDB.Description);
        Assert.Equal(testCollection.Id, testCollectionFromDB.Id);
        Assert.Equal(testCollection.IsPublic, testCollectionFromDB.IsPublic);
        Assert.Equal(testCollection.LayoutSettings, testCollectionFromDB.LayoutSettings);
        Assert.Equal(testCollection.Name, testCollectionFromDB.Name);
        Assert.Equal(testCollection.UserId, testCollectionFromDB.UserId);
    }
}

测试调用了两个方法,这里是控制器方法:

[HttpGet("{id}")]
public Collection Get(Guid id)
{
    var sql = @"SELECT * FROM Collections WHERE id = @id";
    using (var connection = new SqlConnection(ConnectionString))
    {
        var collection = connection.Query<Collection>(sql, new { id = id }).First();
        return collection;
    }
}

这是辅助方法:

public static void AddCollections(List<Collection> collections, string connectionString)
{
    using (var db = new DataClassesDataContext(connectionString))
    {
        db.Collections.InsertAllOnSubmit(collections);
        db.SubmitChanges();
    }
}

(请注意,我在控制器方法中使用 Dapper 作为微型 ORM,因此,为了避免在测试中可能出现的重复错误,我在测试中使用 LINQ to SQL 来代替设置和清理测试数据。)

单元测试的class构造函数和Dispose方法中也有数据库调用。如果需要,我可以将它们添加到 post。

好的,看起来您的应用程序中存在死锁的普通情况,需要处理它 - 您在应用程序方面的计划是什么?

测试及其数据操纵可能会成为同一事物的牺牲品。 xUnit 没有任何东西可以解决这个问题,我强烈认为它不应该。

所以在测试和应用中,你都需要failure/retry管理。

对于网络应用程序,您可以向他们发射一张鲸鱼的图片,然后让他们再次尝试模式,但最终您想要一个真正的解决方案。

对于测试,您不想要鲸鱼并且肯定想要处理它,即不脆弱。

我会使用 Poly 将重试装饰包裹在应用程序或容易出现重大失败的测试中的任何地方——你的练习是弄清楚什么是 重要的 在你的上下文中失败。


在正常情况下,具有单个 reader/writer 同步操作的数据库不应死锁。分析它发生的原因是在数据库端进行分析的问题。如果例如,那一边的工具也可能会很快向您展示。您的整个被测系统的某些方面导致了竞争工作。

(显然您的代码片段不完整,因为 CollectionsController.Get(testCollection.Id) 与控制器方法不是 static 的事实之间存在脱节 - 本次讨论的重点不应该落在 IMO 的那个级别虽然)