如何为每个测试创建单独的内存数据库? [英] How to create separate in memory database for each test?

查看:31
本文介绍了如何为每个测试创建单独的内存数据库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 .NET Core 3.0 上使用 xunit 编写测试,但内存数据库出现问题.我需要为每个测试创建一个单独的数据库,但现在我创建了一个导致问题的数据库,但我不知道如何为每个测试创建一个新数据库.

I'm writing a test with xunit on .NET Core 3.0 and I have a problem with the in-memory database. I need a separate database for each test but now I create a single database that causes problems, but I have no idea how to create a new database for each test.

public class AccountAdminTest : IClassFixture<CustomWebApplicationFactory<Startup>>
{
    private readonly HttpClient _client;
    private IServiceScopeFactory scopeFactory;
    private readonly CustomWebApplicationFactory<Startup> _factory;
    private ApplicationDbContext _context;

    public AccountAdminTest(CustomWebApplicationFactory<Startup> factory)
    {
        _factory = factory;
        _client = _factory.CreateClient(new WebApplicationFactoryClientOptions
        {
            AllowAutoRedirect = true,
            BaseAddress = new Uri("https://localhost:44444")
        });

        scopeFactory = _factory.Services.GetService<IServiceScopeFactory>();
        var scope = scopeFactory.CreateScope();
        _context = scope.ServiceProvider.GetService<ApplicationDbContext>();
    }
}

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.ConfigureTestServices(services =>
        {
            var descriptor = services.SingleOrDefault(
                d => d.ServiceType ==
                    typeof(DbContextOptions<ApplicationDbContext>));

            if (descriptor != null)
            {
                services.Remove(descriptor);
            }

            services.AddDbContext<ApplicationDbContext>((options, context) =>
            {
                context.UseInMemoryDatabase("IdentityDatabase");
            });
        });
    }
}

<小时>

现在看起来像这样,但仍然不起作用.当我改变 AddDbContext 的生命周期时,它不会改变任何东西.


Now it's look like this but still dosen't work. When i change lifetime on AddDbContext it doesn't change anything.

public class AccountAdminTest : IDisposable
{
    public AccountAdminTest(ITestOutputHelper output)
    {
        this.output = output;

        _factory = new CustomWebApplicationFactory<Startup>();

        _client = _factory.CreateClient(new WebApplicationFactoryClientOptions
        {
            AllowAutoRedirect = true,
            BaseAddress = new Uri("https://localhost:44444")
        });

        scopeFactory = _factory.Services.GetService<IServiceScopeFactory>();
        _scope = scopeFactory.CreateScope();
        _context = _scope.ServiceProvider.GetService<ApplicationDbContext>();


        var _user = User.getAppAdmin();
        _context.Add(_user);
        _context.SaveChanges(); //Here i got error on secound test. It says "An item with the same key has already been added"
    }

    public void Dispose()
    {
        _scope.Dispose();
        _factory.Dispose();
        _context.Dispose();
        _client.Dispose();
    }

<小时>

使用 Guid 作为数据库名称时无法获取令牌.它说用户名/密码无效.我使用 IdentityServer 进行身份验证


I can't get token when use Guid as db name. It says that username/password is not valid. I use IdentityServer for authentication

public async Task<string> GetAccessToken(string userName, string password, string clientId, string scope)
        {
            var disco = await _client.GetDiscoveryDocumentAsync("https://localhost:44444");
            if (!String.IsNullOrEmpty(disco.Error))
            {
                throw new Exception(disco.Error);
            }
            var response = await _client.RequestPasswordTokenAsync(new PasswordTokenRequest
            {
                Address = disco.TokenEndpoint,
                ClientId = clientId,
                Scope = scope,
                UserName = userName,
                Password = password,
            });
            return response.AccessToken;
        }

推荐答案

您需要更改的只是这里的代码:

All you need to change is this code here:

services.AddDbContext<ApplicationDbContext>((options, context) =>
{
    context.UseInMemoryDatabase("IdentityDatabase");
});

代替常量值"IdentityDatabase",使用类似Guid.NewGuid().ToString():

Instead of the constant value "IdentityDatabase", use something like Guid.NewGuid().ToString():

context.UseInMemoryDatabase(Guid.NewGuid().ToString());

然后,每次获取上下文时,它将使用一个新的内存数据库.

Then, every time the context is fetched, it will be using a new in-memory database.

这篇关于如何为每个测试创建单独的内存数据库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆