OnConfiguring DbContextOptionsBuilder使我的数据库测试失败

时间:2019-11-30 02:41:30

标签: c# asp.net-core xunit.net

我正在尝试测试是否将我的数据保存在数据库中。当我创建一个ApplicationDbContext时 带有内存数据库SqliteConnection连接的参数集的对象,我的测试失败。我得到一个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);
            }
        }

谢谢, 莱迪

1 个答案:

答案 0 :(得分:0)

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

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服务器测试我的数据是否可以持久化(由于对象关系映射功能,我首选它)。