Xunit тестирует репозитории EFcore InMemory DB

Я пытаюсь выполнить модульное тестирование репозиториев, я использую опцию InMemory в EFCore. Это метод

    [Fact]
    public async Task GetCartsAsync_Returns_CartDetail()
    {
        ICartRepository sut = GetInMemoryCartRepository();
        CartDetail cartdetail = new CartDetail()
        {
            CommercialServiceName = "AAA"
        };

        bool saved = await sut.SaveCartDetail(cartdetail);

        //Assert  
        Assert.True(saved);
        //Assert.Equal("AAA", CartDetail[0].CommercialServiceName);
        //Assert.Equal("BBB", CartDetail[1].CommercialServiceName);
        //Assert.Equal("ZZZ", CartDetail[2].CommercialServiceName);
    }


    private ICartRepository GetInMemoryCartRepository()
    {
        DbContextOptions<SostContext> options;
        var builder = new DbContextOptionsBuilder<SostContext>();
        builder.UseInMemoryDatabase($"database{Guid.NewGuid()}");
        options = builder.Options;
        SostContext personDataContext = new SostContext(options);
        personDataContext.Database.EnsureDeleted();
        personDataContext.Database.EnsureCreated();
        return new CartRepository(personDataContext);
    }

Я получаю сообщение об ошибке

   System.TypeLoadException : Method 'ApplyServices' in type 
   'Microsoft.EntityFrameworkCore.Infrastructure.Internal.InMemoryOptionsExtension' from assembly 
   'Microsoft.EntityFrameworkCore.InMemory, Version=1.0.1.0, Culture=neutral, 
   PublicKeyToken=adb9793829ddae60' does not have an implementation.


   Microsoft. 
  EntityFrameworkCore.InMemoryDbContextOptionsExtensions.UseInMemoryDatabase(DbContextOptionsBuilder 
   optionsBuilder, String databaseName, Action`1 inMemoryOptionsAction)


    Microsoft.EntityFrameworkCore.InMemoryDbContextOptionsExtensions.UseInMemoryDatabase[TContext] 
   (DbContextOptionsBuilder`1 optionsBuilder, String databaseName, Action`1 inMemoryOptionsAction)

Моя ссылка взята с https://www.carlrippon.com/testing-ef-core-repositories-with-xunit-and-an-in-memory-db/

Пожалуйста, предложите мне, где я ошибаюсь с текущей реализацией. Заранее спасибо


person Sagar Jagadesh    schedule 14.11.2019    source источник


Ответы (1)


Я предлагаю прочитать официальную документацию Microsoft об интеграционном тестировании.

https://docs.microsoft.com/fr-fr/aspnet/core/test/integration-tests?view=aspnetcore-3.0

Во-вторых, если вы начнете добавлять этот шаблон для создания своих тестов с базой данных в памяти, вы очень скоро перестанете это делать.

Для интеграционных тестов вы должны быть рядом с вашей конфигурацией разработки.

Здесь мои файлы конфигурации и использование в моем CustomerController:

Файл запуска интеграции

Пусть все думают о создании базы данных и внедрении зависимостей

public class IntegrationStartup : Startup
    {
        public IntegrationStartup(IConfiguration configuration) : base(configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public override void ConfigureServices(IServiceCollection services)
        {
            services.AddEntityFrameworkInMemoryDatabase().BuildServiceProvider();

            services.AddDbContext<StreetJobContext>(options =>
            {
                options.UseInMemoryDatabase("InMemoryAppDb");
            });


            //services.InjectServices();
            //here you can set your ICartRepository DI configuration


            services.AddMvc(option => option.EnableEndpointRouting = false)
                .SetCompatibilityVersion(CompatibilityVersion.Version
public class CustomerControllerTest : IClassFixture<CustomWebApplicationFactory<IntegrationStartup>>
    {
        private readonly HttpClient _client;
        private readonly CustomWebApplicationFactory<IntegrationStartup> _factory;
        private readonly CustomerControllerInitialization _customerControllerInitialization;
        public CustomerControllerTest(CustomWebApplicationFactory<IntegrationStartup> factory)
        {
            _factory = factory;
            _client = _factory.CreateClient();
        }
}
0) .AddApplicationPart(Assembly.Load(new AssemblyName("StreetJob.WebApp"))); ConfigureAuthentication(services); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public override void Configure(IApplicationBuilder app, IWebHostEnvironment env) { var serviceScopeFactory = app.ApplicationServices.GetRequiredService<IServiceScopeFactory>(); using (var serviceScope = serviceScopeFactory.CreateScope()) { //Here you can add some data configuration } app.UseMvc(); }

Поддельный стартап

это очень похоже на то, что в документации Microsoft

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override IWebHostBuilder CreateWebHostBuilder()
    {
        return WebHost.CreateDefaultBuilder(null)
            .UseStartup<TStartup>();
    }

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.UseSolutionRelativeContentRoot(Directory.GetCurrentDirectory());

        builder.ConfigureAppConfiguration(config =>
        {
            config.AddConfiguration(new ConfigurationBuilder()
               //custom setting file in the test project
                .AddJsonFile($"integrationsettings.json")
                .Build());
        });

        builder.ConfigureServices(services =>
        {
        });
    }
}

Контроллер

public class CustomerControllerTest : IClassFixture<CustomWebApplicationFactory<IntegrationStartup>>
    {
        private readonly HttpClient _client;
        private readonly CustomWebApplicationFactory<IntegrationStartup> _factory;
        private readonly CustomerControllerInitialization _customerControllerInitialization;
        public CustomerControllerTest(CustomWebApplicationFactory<IntegrationStartup> factory)
        {
            _factory = factory;
            _client = _factory.CreateClient();
        }
}

При такой настройке тестирование интеграционных тестов очень похоже на контроллер разработки. Это неплохая конфигурация для разработчиков TDD.

person OrcusZ    schedule 14.11.2019