Я следил за официальной документацией .Net по интеграционным тестам, и у меня возникла проблема: моя база данных Sqlite, к которой я обращаюсь в тестах, отличается от базы данных в моем контроллере. Вот пример:
/// IntegrationTest.cs
public class ClientTests : IClassFixture {
[Fact]
public async void Post_ShouldCreateClient()
{
var client = await CreateClientWithAuth(); // Here we create a user in the database
var content = JsonEncode( ... );
var user = await userManager.Users.ToListAsync(); // List with one user
Assert.Single( user ); // Pass: User exists
var result = await client.PostAsync( "/Api/Client", content ); // Fail: Database empty
}
Если я запрошу список пользователей в моем контроллере, я получу пустой список, хотя в тесте только что было подтверждено, что пользователь существует.
/// Controller.cs
[HttpPost]
public async Task Create( [Bind]CreateClient model )
{
/// ...
var users = await _userManager.Users.ToListAsync(); // Empty list???
}
Вот как я регистрирую свои тестовые службы:
public class InvoicerApplicationFactory : WebApplicationFactory
{
private SqliteConnection? _connection;
protected override void ConfigureWebHost( IWebHostBuilder builder )
{
builder.ConfigureServices( services =>
{
services.RemoveAll();
services.RemoveAll();
// Create the connection to database
_connection = new SqliteConnection( "DataSource=:memory:" );
_connection.Open();
services.AddSingleton( container => _connection );
services.RemoveAll();
services.AddDbContext( ( container, options ) =>
{
options.UseSqlite( _connection );
} );
// Migrate the database
var sp = services.BuildServiceProvider();
var scope = sp.CreateScope();
var db = scope.ServiceProvider.GetRequiredService();
db.Database.EnsureCreated();
} );
builder.UseEnvironment( "Testing" );
}
protected override void Dispose( bool disposing )
{
base.Dispose( disposing );
_connection?.Dispose();
}
}
Наконец, вот как выглядит моя функция CreateClientWithAuth(). Это функция, которую я использую для создания клиента с имитацией аутентификации и пользователем по умолчанию.
< pre class="lang-cs Prettyprint-override">protected async Task CreateClientWithAuth( string email = "admin@test.com", string password = "admin" )
{
return CreateClientWithAuth( await CreateUser( email, password ) );
}
protected HttpClient CreateClientWithAuth( User authenticatedUser )
{
this.authenticatedUser = authenticatedUser;
var client = factory.WithWebHostBuilder( builder =>
{
builder.ConfigureTestServices( services =>
{
services.AddAuthentication( defaultScheme: "TestScheme" )
.AddScheme(
"TestScheme", options => {
options.DefaultUser = authenticatedUser;
} );
} );
} )
.CreateClient();
return client;
}
Кроме того, когда я вместо этого использую файл :memory: в качестве источника, проблема исчезает, поэтому я предполагаю, что это проблема тестов, которые не используют одно и то же соединение Sqlite с остальной частью проекта. Мои тесты расположены в другом проекте, чем файл Program.cs, но они находятся в том же решении и на них есть ссылки.
Изменить:
Вот как я регистрирую удостоверение:
/// In Program.cs
services.AddIdentityApiEndpoints()
.AddRoles()
.AddEntityFrameworkStores();
В контроллере userManager извлекается с помощью DI, в тестах я использую этот код:
// factory is InvoicerApplicationFactory, passed through the constructor of the test class:
public ApiTest( InvoicerApplicationFactory appfactory )
{
factory = appfactory;
userManager = factory.Services.GetRequiredService();
}
Подробнее здесь: https://stackoverflow.com/questions/791 ... controller
Состояние базы данных памяти SQLite не используется совместно интеграционным тестом и контроллером в .NET Core с xUnit ⇐ C#
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение