Ответ
Да, активно использовал InMemory Database (провайдер Microsoft.EntityFrameworkCore.InMemory) для модульного и интеграционного тестирования кода, работающего с EF Core.
Зачем это нужно? Для создания быстрых, изолированных тестов, которые не требуют развертывания реальной СУБД (SQL Server, PostgreSQL) и не оставляют после себя данных.
Пример юнит-теста с InMemory DbContext:
[Fact]
public async Task GetUserById_ShouldReturnCorrectUser()
{
// 1. Arrange (Подготовка)
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString()) // Уникальное имя для изоляции тестов
.Options;
// Заполняем базу тестовыми данными
using (var context = new ApplicationDbContext(options))
{
context.Users.Add(new User { Id = 1, Name = "Alice", Email = "alice@test.com" });
context.Users.Add(new User { Id = 2, Name = "Bob", Email = "bob@test.com" });
await context.SaveChangesAsync();
}
var repository = new UserRepository(new ApplicationDbContext(options));
// 2. Act (Действие)
var result = await repository.GetByIdAsync(1);
// 3. Assert (Проверка)
Assert.NotNull(result);
Assert.Equal("Alice", result.Name);
Assert.Equal("alice@test.com", result.Email);
}
Важные ограничения и нюансы:
- Не полная эмуляция СУБД: InMemory провайдер не обеспечивает:
- Референциальную целостность (ограничения внешних ключей часто игнорируются).
- Сложные ограничения уникальности.
- Транзакционность в полном смысле (например,
Rollback). - Конкретное SQL-поведение (хранимые процедуры, пользовательские функции, специфичные типы данных).
- Изоляция тестов: Важно использовать
Guid.NewGuid().ToString()для имени базы, чтобы каждый тест работал с чистым состоянием. - Альтернативы для более точного тестирования:
- SQLite in-memory mode: Более точно эмулирует реляционную БД, поддерживает транзакции и ограничения.
- TestContainers: Запускает реальную СУБД (PostgreSQL, SQL Server) в Docker-контейнере — идеально для интеграционных тестов, но медленнее.
Вывод: InMemory Database — отличный инструмент для быстрых юнит-тестов логики приложения, но для тестирования сложных запросов или миграций лучше использовать более приближенные к продакшену варианты.