Build config to pass in to dbcontext as an argument so I can use it in a unit test

asp.net-core c# entity-framework entity-framework-core unit-testing

Question

Here is my db context class

  public class WorldContext : IdentityDbContext<WorldUser>
  {
    private IConfigurationRoot _config;
    public WorldContext(IConfigurationRoot config, DbContextOptions options): base(options)
    {
        _config = config;
    }
    public DbSet<Trip> Trips { get; set; }
    public DbSet<Stop> Stops { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.UseSqlServer(_config["ConnectionStrings:WorldContextConnection"]);
    }
  }

Here is the part of my test code where I'm trying to create an instance of my dbcontext.

            var builder = new ConfigurationBuilder();
            var config = builder.Build();
            var options = new DbContextOptionsBuilder<WorldContext>()
                .UseInMemoryDatabase(Guid.NewGuid().ToString())
                .Options;
            var context = new WorldContext(config, options);

No errors in VS and builds fine, but the test fails with:

Message: System.ArgumentNullException : Value cannot be null. Parameter name: connectionString

[There is reference to this in the stack trace:]

at TheWorld.DAL.Models.WorldContext.OnConfiguring(DbContextOptionsBuilder optionsBuilder)

1
1
9/26/2017 10:41:39 PM

Accepted Answer

First, create an instance of DbContextOptions<WorldContext> in your test class:

DbContextOptions<WorldContext> options;
var builder = new DbContextOptionsBuilder<WorldContext>();
builder.UseInMemoryDatabase(Guid.NewGuid().ToString());
options = builder.Options;

DbContextOptions instance will tell all the configurations for WorldContext, which database it will connect etc. Since it is a in-memory database, you don't need to send a connection string (IMHO). So there is no need for IConfigurationRoot parameter in your WoldContext contructor.


Then, create an instance of WorldContext class and use it:

var context = new WorldContext(options);

Or you are saying I don't want to change my constructor, this is necessary, then:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    base.OnConfiguring(optionsBuilder);
    if(string.IsNullOrEmpty(_config["ConnectionStrings:WorldContextConnection"]))
    {
        optionsBuilder.UseInMemoryDatabase(Guid.NewGuid().ToString());
    }
}
1
9/27/2017 11:23:09 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow