2016-12-05 98 views
1

我使用以下代碼中的測試設置一個單元測試:實體框架核心1.1內存數據庫失敗添加新實體

var simpleEntity = new SimpleEntity(); 
var complexEntity = new ComplexEntity 
{ 
    JoinEntity1List = new List<JoinEntity1> 
    { 
     new JoinEntity1 
     { 
      JoinEntity2List = new List<JoinEntity2> 
      { 
       new JoinEntity2 
       { 
        SimpleEntity = simpleEntity 
       } 
      } 
     } 
    } 
}; 
var anotherEntity = new AnotherEntity 
{ 
    ComplexEntity = complexEntity1 
}; 

using (var context = databaseFixture.GetContext()) 
{ 
    context.Add(anotherEntity); 
    await context.SaveChangesAsync(); 
} 

當達到SaveChangesAsync EF拋出以下消息一個ArgumentException:

具有相同密鑰的項目已被添加。 Key:1

我使用夾具以及單元測試類,它使用相同類型的對象填充數據庫,雖然對於此測試,我想要這個特定的設置,所以我想添加這些新的實體到內存數據庫中。我已經嘗試在DbSet(而不是DbContext)上添加實體,並單獨添加所有三個實體無濟於事。然而,我可以單獨添加「simpleEntity」(因爲它沒有添加到燈具中),但是當我嘗試添加「complexEntity」或「anotherEntity」時,EF會立即抱怨。

看來EF在內存數據庫中無法處理多個Add的上下文的不同實例。有沒有什麼解決方法,或者我在我的設置中做錯了什麼?

在這種情況下,databaseFixture是這個類的一個實例:

namespace Test.Shared.Fixture 
{ 
    using Data.Access; 
    using Microsoft.EntityFrameworkCore; 
    using Microsoft.Extensions.DependencyInjection; 

    public class InMemoryDatabaseFixture : IDatabaseFixture 
    { 
     private readonly DbContextOptions<MyContext> contextOptions; 

     public InMemoryDatabaseFixture() 
     { 
      var serviceProvider = new ServiceCollection() 
      .AddEntityFrameworkInMemoryDatabase() 
      .BuildServiceProvider(); 

      var builder = new DbContextOptionsBuilder<MyContext>(); 
      builder.UseInMemoryDatabase() 
        .UseInternalServiceProvider(serviceProvider); 

      contextOptions = builder.Options; 
     } 

     public MyContext GetContext() 
     { 
      return new MyContext(contextOptions); 
     } 
    } 
} 
+0

你的模型和環境是什麼樣的? –

回答

1

您可以使用收藏燈具解決這個問題,這樣你就可以份額此夾具在多個測試類。這樣,你不建立你的情況下多次,因此,你不會得到這個異常:

Some information about collection Fixture

我自己的例子:

[CollectionDefinition("Database collection")] 
public class DatabaseCollection : ICollectionFixture<DatabaseFixture> 
{ } 

[Collection("Database collection")] 
public class GetCitiesCmdHandlerTests : IClassFixture<MapperFixture> 
{ 
    private readonly TecCoreDbContext _context; 
    private readonly IMapper _mapper; 

    public GetCitiesCmdHandlerTests(DatabaseFixture dbFixture, MapperFixture mapFixture) 
    { 
     _context = dbFixture.Context; 
     _mapper = mapFixture.Mapper; 
    } 

    [Theory] 
    [MemberData(nameof(HandleTestData))] 
    public async void Handle_ShouldReturnCountries_AccordingToRequest(
     GetCitiesCommand command, 
     int expectedCount) 
    { 
     (...) 
    } 

    public static readonly IEnumerable<object[]> HandleTestData 
     = new List<object[]> 
     { 
      (...) 
     }; 
} 

}

祝你好運, Seb