簡體   English   中英

如何在DbContext-主鍵中沒有沖突的情況下並行運行Xunit?

[英]How to Run Xunit in Parallel without Collision in DbContext - Primary Key?

我正在使用內存數據庫創建Xunit測試。 如果單獨運行,則測試可以正確執行。 但是,如果並行運行,則它們會由於dbcontext中的主鍵問題而發生沖突。

解決此問題的最佳選擇是什么?

  1. Xunit是否具有拆卸功能? 聽說xunit不支持此功能。
  2. 我應該按順序運行測試嗎?
  3. 應該繼續使用其他密鑰ID嗎?

嘗試研究xunit文檔,才剛剛開始學習.net編程。

錯誤:

"System.ArgumentException : An item with the same key has already been added. Key: 2"

碼:

2是主鍵,使用兩次

public class ProductAppServiceTest
{
    public TestContext context;
    public IMapper mapper;
    public ProductAppServiceTest()
    {
        var options = new DbContextOptionsBuilder<TestContext>()
            .UseInMemoryDatabase(databaseName: "TestDatabase")
            .Options;
        context = new TestContext(options);

        ApplicationServicesMappingProfile applicationServicesMappingProfile = new ApplicationServicesMappingProfile();
        var config = new MapperConfiguration(cfg =>
        {
            cfg.AddProfile(applicationServicesMappingProfile);
        });
        mapper = config.CreateMapper();
    }

    [Fact]
    public async Task Get_ProductById_Are_Equal()
    {
        context.Product.Add(new Product { ProductId = 2, ProductCode = "123", ProductName = "ABC" });
        context.SaveChanges();

        var ProductRepository = new ProductRepository(context);
        var ProductAppService = new ProductAppService(ProductRepository, mapper);
        var ProductDto = await ProductAppService.GetProductById(2);

        Assert.Equal("123", ProductDto.ProductCode);
    }

    [Fact]
    public async Task Get_ProductPrice_Are_Equal()
    {
        context.Product.Add(new Product { ProductId = 2, ProductCode = "123", ProductName = "ABC" });
        context.SaveChanges();

        var ProductRepository = new ProductRepository(context);
        var ProductAppService = new ProductAppService(ProductRepository, mapper);
        var ProductDto = await ProductAppService.GetProductById(2);
        //Goes into Enum table to validate price is 5
        Assert.Equal("5", ProductDto.Price);
    }

這里的問題是,每個測試都使用相同的內存數據庫。 盡管您可以拆除並為每個測試創建數據庫,但通常更容易為每個測試使用唯一的數據庫。

注意:每個測試使用同一數據庫的原因是因為您使用的是靜態數據庫名稱。

XUnit在每次測試之前都會調用測試類構造函數,因此,您可以使用數據庫名稱的guid為每個測試創建唯一的內存數據庫。

var options = new DbContextOptionsBuilder<TestContext>()
                      .UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
                      .Options;
context = new TestContext(options);

示例測試將不會正確並行執行,因為它們是同一集合的成員。

默認情況下,每個測試類都是唯一的測試集合。 同一測試類中的測試不會並行運行。 -https://xunit.net/docs/running-tests-in-parallel

源代碼中的TestContext是什么,它是某種單例嗎? 如果是這樣,則由於兩個測試都在同一個集合中而在並行運行時,它將在xUnit啟動的類的2個實例之間共享。 (即使在同一集合中,也會創建每個類的新副本)。

如果您確實需要在集合或部件中共享,我建議您使用內置的TestFixture功能或實現部件治具。

通過構造函數和IDisposable或在測試類上實現IAsyncLifetime來實現xUnit中的Setup和Teardown。 注意:當並行運行時,DisposeAsync將等待測試運行,然后再開始每個Dispose。

public class UnitTest : IDisposable, IAsyncLifetime
{
    public UnitTest()
    {
        //First
    }

    public Task InitializeAsync()
    {
        //Second
    }

    [Fact]
    public async Task Test1()
    {
        //Third
    }

    public Task DisposeAsync()
    {
        //Forth
    }

    public void Dispose()
    {
        //Fifth
    }
}

對於避免多處理任務更改其他任務正在使用的數據的問題,我的簡單答案是開發一個數據結構,在該數據結構中,每個任務都傳遞一個索引,該索引告訴它們在並行作業全部使用時要使用結構的哪一部分完成后,可以將數據重新組合為您通常使用的原始主數據結構。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM