#c# #asp.net-core #testing #entity-framework-core #integration-testing
Вопрос:
Я написал несколько интеграционных тестов для своего приложения ASP .NET Core, используя xUnit и WebApplicationFactory<Startup>
класс. Потратив много времени на выяснение того, почему я получаю много SqlServerExceptions
всякий раз, когда они запускаются в первый раз (т. Е. Когда база данных еще не существует), я понял, что проблема в том, что запуск context.Database.Migrate()
в моем Startup.cs
не очень хорошо работает с фабрикой. Я думаю, что, возможно, это связано с параллельными тестами и состоянием гонки, в результате чего две фабрики думают, что базы данных еще нет, и пытаются выполнить одни и те же миграции.
Я получаю такие ошибки, как следующие:
Microsoft.Data.SqlClient.SqlException : Database 'MyApplicationDB' already exists. Choose a different database name.
...
Microsoft.Data.SqlClient.SqlException : There is already an object named 'AspNetRoles' in the database.
...
Microsoft.Data.SqlClient.SqlException : There is already an object named '__EFMigrationsHistory' in the database.
и т.д.
Я «решил» проблему, удалив шаг миграции при запуске и вместо этого запустив миграции с помощью интерфейса dotnet
командной строки и запустив dotnet test
.
Мой вопрос: Есть ли способ настроить WebApplicationFactory
s так, чтобы они хорошо взаимодействовали друг с другом, когда в классе происходит этап миграции Startup
? Или миграция при запуске вообще плохая идея?
Комментарии:
1. Да… не проводите тесты параллельно.
2. Какую версию .net core вы используете, вы можете прочитать в этой статье, там есть хорошие примеры и пояснения, которые могут вам помочь: andrewlock.net/converting-integration-tests-to — сетевое ядро-3/
3. @Chaodeng что-то пошло не так с вашей гиперссылкой. andrewlock.net/converting-integration-tests-to-net-core-3
Ответ №1:
Может быть, вы могли бы воспользоваться InMemoryDatabase
? В этом случае вы можете сделать что-то подобное в производном WebApplicationFactory
:
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.ConfigureServices(services =>
{
services.AddDbContext<IdentityContext>(o =>
{
// Make sure that every test has its own database to prevent concurrency issues in tests.
var inMemoryDbName = Guid.NewGuid().ToString();
o.UseInMemoryDatabase(inMemoryDbName);
});
});
}
Комментарии:
1. Спасибо, я попробую, когда представится возможность.