Xunit测试EFcore存储库InMemory DB

时间:2019-11-14 10:39:39

标签: c# .net entity-framework .net-core xunit.net

我正在尝试对存储库进行单元测试,我在EFCore中使用InMemory选项。这是方法

    [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/

请建议我当前的实现方式出了什么问题。在此先感谢

1 个答案:

答案 0 :(得分:0)

我建议阅读有关集成测试的Microsoft官方文档。

this

第二,我开始添加这种样板,使用内存数据库创建测试,您将很快停止这样做。

对于集成测试,您应该靠近开发配置。

这是我的配置文件和我的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_3_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开发人员来说,这是一个很好的配置。