首页 > 解决方案 > OnConfiguring DbContextOptionsBuilder 使我的数据库测试失败

问题描述

我正在尝试测试我的数据是否保存在数据库中。当我使用内存数据库 SqliteConnection 连接的参数集创建 ApplicationDbContext 对象时,我的测试失败。我得到一个 NullReferenceException。当我删除 ApplicationDbContext 对象中的覆盖 OnConfiguring 方法以连接使用我的其他构造函数设置的秘密时,我不再收到异常并且我的测试通过了。

在保持连接的秘密设置的同时进行此测试的最简单方法是什么?

这些是我的一些课程:

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        private readonly AppSecrets _DbInfo;

        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IOptions<AppSecrets> 
        DbInfo) : base(options)
        {
            _DbInfo = DbInfo.Value ?? throw new ArgumentException(nameof(DbInfo));
        }

        // Added for unit test
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options): base(options){    }

        protected override void OnConfiguring(DbContextOptionsBuilder options) =>
            options.UseSqlServer($"{_DbInfo.Database};User ID={_DbInfo.User};Password= {_DbInfo.Password};{_DbInfo.Options};");

        public DbSet<UserBudget> Budgets { get; set; }
    }

在 StartUp.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<AppSecrets>(Configuration.GetSection("MyBudgetDB"));

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
        }

测试

[Fact]
        public async Task CreateBudget_CreatesCorrectly()
        {
            const string budgetName = "General budget";
            double amount = 1000.0;
            var connection = new SqliteConnection("DataSource=:memory:");
            connection.Open();
            var options = new DbContextOptionsBuilder<ApplicationDbContext>()
                .UseSqlite(connection)
                .Options;

            // Run the test against one instance of the context
            using (var context = new ApplicationDbContext(options))
            {
                context.Database.EnsureCreated();
                var service = new BudgetService(context);
                var cmd = new CreateBudgetCommand
                {
                    InitAmount = amount,
                };
                var user = new ApplicationUser
                {
                    Id = 123.ToString()
                };
                var recipeId = service.CreateBudget(cmd, user);
            }

            // Use a separate instance of the context to verify correct data was saved to database
            using (var context = new ApplicationDbContext(options))
            {
                Assert.Equal(1000.0, await context.Budgets.CountAsync());
                var budget = await context.Budgets.SingleAsync();
                Assert.Equal(amount, budget.InitAmount);
            }
        }

谢谢,莱迪

标签: c#asp.net-corexunit.net

解决方案


我尝试使用 SqlConnection 并在测试中手动设置 IOptions< AppSecrets > 但这更复杂,我得到了同样的错误。我为此采取了最简单,最合适的方式(我不知道这很容易);通过从 ApplicationDbContext 中删除 OnConfiguring() 方法并在 StartUp 中添加这些设置:

启动.cs

 var config = new AppSecrets();
            Configuration.Bind("MyBudgetDB", config);
            services.AddSingleton(config);

            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    $"{config.Database};User ID={config.User};Password={config.Password};{config.Options};"));
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {   }

        public DbSet<UserBudget> Budgets { get; set; }
    }

我现在可以测试我的数据是否正在使用 Sqlite 服务器进行持久化(由于对象关系映射功能,我更喜欢它)。


推荐阅读