Интеграционные тесты xUnit в.NET Core выдают ошибку "Элемент с таким же ключом уже добавлен"
Я использую xUnit для выполнения интеграционных тестов в приложении.NET Core. Я следую за разделом интеграционных тестов этого поста. Он познакомил меня с TestFixture, которая размещает проект на сервере в памяти. Код запуска инициализирует базу данных в памяти с двумя записями в таблице активов. Тесты показаны ниже.
У меня проблема в том, что когда я запускаю эти тесты, они терпят неудачу с ошибкой: элемент с тем же ключом уже был добавлен
Я предполагаю, что это потому, что Автозагрузка пытается добавить те же две записи в базу данных для каждого теста. Если я запускаю тесты во второй раз, они проходят. Когда я запускаю их в третий раз, они терпят неудачу и чередуются вот так. Когда я помещаю точку останова в код Starup, который инициализирует базу данных, создается впечатление, что два потока пытаются выполнить строку останова, потому что когда я нажимаю F10, чтобы перейти к следующей строке, выполнение остается на той же строке. Как я могу подтвердить, что это проблема? Если это действительно так!
public class AssetControllerTests : IClassFixture<TestFixture<ManagementSystemCore.Startup>>
{
private readonly HttpClient _client;
public AssetControllerTests(TestFixture<ManagementSystemCore.Startup> fixture)
{
_client = fixture.Client;
}
private List<Asset> GetTestAssets()
{
return Startup.GetTestAssets();
}
[Fact]
public async Task Assets_ReturnsAViewResult_WithListOfAssets()
{
// Arrange
var mockRepo = new Mock<IAssetRepository>();
mockRepo.Setup(repo => repo.ListAsync()).Returns(Task.FromResult(GetTestAssets()));
try
{
var controller = new AssetController(mockRepo.Object);
// Act
var result = await controller.Assets();
// Assert
var viewResult = Assert.IsType<ViewResult>(result);
var model = Assert.IsAssignableFrom<IEnumerable<AssetViewModel>>(viewResult.ViewData.Model);
Assert.Equal(2, model.Count());
}
catch (Exception e)
{
var msg = e.Message;
}
}
[Fact]
public async Task Details_ReturnsViewResult_WithOneAsset()
{
// Arrange - get an asset known to exist
var testAssets = Startup.GetTestAssets();
var id = testAssets.Select(a => a.Id).First();
// Act
var response = await _client.GetAsync("/asset/details/" + id);
// Assert
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
Assert.True(responseString.Contains(testAssets.Select(a => a.SerialNumber).First()));
Assert.True(responseString.Contains(testAssets.Select(a => a.PartNumber).First()));
}
[Fact]
public async Task PostAsync_ReturnsBadRequest_GivenNullModel()
{
// Arrange & Act
var mockRepo = new Mock<IAssetRepository>();
var controller = new AssetController(mockRepo.Object);
controller.ModelState.AddModelError("error", "some error");
// Act
var result = await controller.PostAsync(null);
// Assert
Assert.IsType<BadRequestObjectResult>(result);
}
}
Вот код запуска:
public class Startup
{
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options => options.UseInMemoryDatabase());
services.AddMvc();
services.AddScoped<ITodoRepository, TodoRepository>();
services.AddScoped<IAssetRepository, AssetRepository>();
services.AddScoped<IValuesRepository, ValuesRepository>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
var repository = app.ApplicationServices.GetService<IAssetRepository>();
InitializeDatabaseAsync(repository).Wait();
}
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Asset}/{action=Index}/{id?}");
});
}
// Load the database with sample assets
public async Task InitializeDatabaseAsync(IAssetRepository repo)
{
var assetList = await repo.ListAsync();
if (!assetList.Any())
{
foreach (var asset in GetTestAssets())
{
await repo.AddAsync(asset);
}
}
}
public static List<Asset> GetTestAssets()
{
return new List<Asset>()
{
new Asset("5eb6eb60-72d7-4f51-b209-22a4d97604bd", "SN1234", "PN1234"),
new Asset("4dc5fd59-98d7-3g34-c310-47g5e84987cg", "SN5678", "PN5678")
};
}
}