Инъекция поддельного dbContext внутри Сервиса - интеграционные тесты - PullRequest
0 голосов
/ 10 октября 2019

Я пытаюсь реализовать интеграционный тест, чтобы я мог тестировать свои конечные точки, используя только HttpClient

public async Task TestEndPoint()
{          
    using (var response = await _client.GetAsync($"/api/car/{id}"))
    {
        //...         
    }
}

Я использую класс Fixture, чтобы помочь мне с этим

private readonly TestServer _server;
public Fixture()
{
    var dbContextOptions = new DbContextOptionsBuilder<CarDbContext>()
                    .UseInMemoryDatabase(Guid.NewGuid().ToString())
                    .Options;

    var mockContext = new Mock<CarDbContext>(dbContextOptions);
    var mockOwnerSet = new Mock<DbSet<Owner>>();
    var mockCarSet = new Mock<DbSet<Car>>();
    mockContext.Setup(m => m.Owners).Returns(mockOwnerSet.Object);
    mockContext.Setup(m => m.Cars).Returns(mockCarSet.Object);          

    var carService = new CarService(mockContext.Object);

    _server = new TestServer(new WebHostBuilder()
        .ConfigureAppConfiguration((context, conf) =>
        {
            conf.AddJsonFile(@Directory.GetCurrentDirectory() + "../appsettings.json");
        }).UseStartup<Startup>()
            .ConfigureServices(services =>
            {
                services.AddDbContext<CarDbContext>(options => options.UseInMemoryDatabase("Test"));
                services.AddScoped<ICarService>(_ => carService);
            })
        );

    Client = _server.CreateClient();    
}   

Inside Startup.cs

public class Startup
{
   public void ConfigureServices(IServiceCollection services)
   {
       services.AddDbContext<CarDbContext>(options => { options.UseSqlServer(Configuration.GetConnectionString("Db")); });
       services.AddTransient<ICarService, CarService>();
   }
}

Класс обслуживания

public class CarService: ICarService {
    private readonly CarDbContext _carDbContext;

    public CarService(CarDbContext carDbContext)
    {
        _carDbContext = carDbContext;
    }

    public async Task<Car> GetAsync(int id)
    {
        return await _carDbContext.Cars.FindAsync(id); //this always returns null
    }
}

Мой вопрос: почему не используется контекст mob db внутри CarService

return await _carDbContext.Cars.FindAsync (id); всегда возвращает ноль

Обновление:

private readonly TestServer _server;
public TestServer Server;
public Fixture()
{
    _server = new TestServer(new WebHostBuilder()
        .ConfigureAppConfiguration((context, conf) =>
        {
            conf.AddJsonFile(@Directory.GetCurrentDirectory() + "../appsettings.json");
        }).UseStartup<Startup>()
            .ConfigureServices(services =>
            {
                services.AddDbContext<CarDbContext>(options => options.UseInMemoryDatabase(Guid.NewGuid().ToString()));
            })
        );

    Client = _server.CreateClient();    
    Server = _server;
}

// внутри метода тестирования

using (var scope = _server.Host.Services.CreateScope())
{
    var db = scope.ServiceProvider.GetRequiredService<CarDbContext>();
    db.Database.EnsureDeleted();
    Utilities.Seed(db);
}

ИДанные семян

public static class Utilities
{
    public static void Seed(CarDbContext db)
    {
         db.Cars.Add(new Car("1", "White", "Toyota"));        
         db.SaveChanges(true);
        }
  }

Что именно я делаю не так, где? Я все еще получаю нулевое значение при получении данных в

public async Task<Car> GetAsync(int id)
{
    return await _carDbContext.Cars.FindAsync(id); //this always returns null
}

1 Ответ

3 голосов
/ 10 октября 2019

Вам не нужно издеваться над контекстом или вашим сервисом. Удалите все до строки _server = new TestServer. В настройках веб-хостинга вы уже настроили контекст для использования провайдера в памяти, так что это все, что необходимо. Контекст будет внедрен в сервис, а сервис будет внедрен там, где это необходимо. Здесь меняется только контекстная связь. Вместо того, чтобы использовать что-то реальное, например, экземпляр SQL Server, он просто будет хранить и извлекать данные из памяти.

Единственное, что вам нужно сделать для теста, это заполнить «базу данных» данными, которые выхочу проверить. В вашем тесте вам нужно получить доступ к экземпляру тестового сервера и выполнить:

using (var scope = _server.Host.Services.CreateScope())
{
    var context = scope.ServiceProvider.GetRequiredService<CarDbContext>();
    context.EnsureDeleted();
    // seed test data
}

// test code
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...