代码之家  ›  专栏  ›  技术社区  ›  Dmytro Kotenko

集成测试中无法在模拟InMemory数据库中播种数据

  •  1
  • Dmytro Kotenko  · 技术社区  · 2 年前

    我有下一个测试类,其中包含一个调用简单api端点的集成测试。

    在这里的设置方法中,我将真实的数据库替换为InMemory,并试图将有关两个城市的信息添加到数据库中。

     public class TestControllerTest
     {
         private WebApplicationFactory<RentAPI.Program> _factory;
         private HttpClient _client;
    
         [SetUp]
         public void Setup()
         {
             _factory = new WebApplicationFactory<RentAPI.Program>().WithWebHostBuilder(builder =>
             {
                 builder.ConfigureTestServices(services =>
                 {
                     var dbContextDescriptor = services.SingleOrDefault(d =>
                         d.ServiceType == typeof(DbContextOptions<ApplicationDbContext>));
    
                     services.Remove(dbContextDescriptor);
    
                     services.AddDbContext<ApplicationDbContext>(options =>
                     {
                         options.UseInMemoryDatabase(Guid.NewGuid().ToString());
                     });
    
                     using var scope = services.BuildServiceProvider().CreateScope();
                     var db = scope.ServiceProvider.GetService<ApplicationDbContext>();
    
                     SeedData(db);
                 });
             });
    
             _client = _factory.CreateClient();
         }
    
         [Test]
         public async Task Test_test()
         {
    
             var response = await _client.GetAsync("/Test");
             var stingResult = await response.Content.ReadAsStringAsync();
    
             Assert.That(stingResult, Is.EqualTo("3"));
         }
    
         [TearDown]
         public void TearDown()
         {
             _client.Dispose();
             _factory.Dispose();
         }
    
         public static void SeedData(ApplicationDbContext context)
         {
             context.Cities.AddRange(
                 new City { Id = 1, Name = "City1" },
                 new City { Id = 2, Name = "City2" }
             );
    
             context.SaveChanges();
         }
     }
    

    这是端点

    [ApiController, Route("[controller]")]
    public class TestController : ControllerBase
    {
        private readonly IUnitOfWork _uow;
    
        public TestController(IUnitOfWork uow) => _uow = uow;
    
        [HttpGet]
        public async Task<ActionResult<string>> Test()
        {
            await _uow.CityRepository.AddAsync(new City() { Id = 99, Name = "Poko" });
            await _uow.CompleteAsync();
    
            var cities = await _uow.CityRepository.FindAllAsync();
            return cities.Count().ToString();
        }
    }
    

    问题是,尽管我试图将城市信息添加到我用于应用程序的数据库中,但当我在测试中调用端点时,这些记录不会出现。

    以下是测试结果:

      String lengths are both 1. Strings differ at index 0.
      Expected: "3"
      But was:  "1"
      -----------^
    
    1 回复  |  直到 2 年前
        1
  •  1
  •   Guru Stron    2 年前

    通过移动 Guid.NewGuid().ToString() 中的 ConfigureTestServices WithWebHostBuilder 。此外,我强烈建议也取消种子设定,因为不鼓励多次调整服务提供商,并可能导致不必要的副作用:

     public void Setup()
     {
          var databaseName = Guid.NewGuid().ToString();
         _factory = new WebApplicationFactory<Program>().WithWebHostBuilder(builder =>
         {
             builder.ConfigureTestServices(services =>
             {
                 var dbContextDescriptor = services.SingleOrDefault(d =>
                     d.ServiceType == typeof(DbContextOptions<ApplicationDbContext>));
    
                 services.Remove(dbContextDescriptor);
    
                 services.AddDbContext<ApplicationDbContext>(options =>
                 {
                     options.UseInMemoryDatabase(databaseName);
                 });
             });
         });
        
         using var scope =  _factory.Services.CreateScope();;
         var db = scope.ServiceProvider.GetService<ApplicationDbContext>();
    
         SeedData(db);
         _client = _factory.CreateClient();
     }
    

    您当前的代码:

    using var scope = services.BuildServiceProvider().CreateScope();
    

    构建一个单独的DI容器,该容器将拥有自己的一组服务,这些服务与测试服务器使用的服务无关(测试服务器将启动自己的容器)。