Entity Framework Core Unique Index testing

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

Question

I have a model class:

public class Work
{
    public long Id { get; set; }

    [Required]
    public string Name { get; set; }
}

I want this Work.Name will be unique, so I define the DbContext:

public class MyDbContext : DbContext
{
    public MyDbContext () : base() { }
    public MyDbContext (DbContextOptions<MyDbContext > options) : base(options) { }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Work>(entity =>
            entity.HasIndex(e => e.Name).IsUnique()
        );
    }
    public DbSet<Work> Works { get; set; }
}

And I want to test this, so I have a test like this:

[Fact]
public void Post_InsertDuplicateWork_ShouldThrowException()
{
    var work = new Work
    {
        Name = "Test Work"
    };

    using (var context = new MyDbContext (options))
    {
        context.Works.Add(work);
        context.SaveChanges();
    }

    using (var context = new MyDbContext (options))
    {
        context.Works.Add(work);
        context.SaveChanges();
    }

    using (var context = new MyDbContext (options))
    {
         Assert.Equal(1, context.Works.Count());
    }
}

( The option object contains settings for InMemoryDatabase)

I don't really know what to check, but the test failed in the Assert, not in the second SaveChanges(). The database (the context) contains two objects with the same Name.

I went over all the relevant questions, but I did not see anyone answering what I was asking.

1
0
3/26/2019 3:33:42 PM

Popular Answer

As others pointed out InMemory database provider ignore all possible constraints.
My suggestion would be then to use Sqlite provider with "in-memory' feature, which will throw an exception for duplicate unique keys.

public MyDbContext CreateSqliteContext()
{
    var connectionString = 
        new SqliteConnectionStringBuilder { DataSource = ":memory:" }.ToString();
    var connection = new SqliteConnection(connectionString);
    var options = new DbContextOptionsBuilder<MyDbContext>().UseSqlite(connection);

    return new MyDbContext(options);
}

private void Insert(Work work)
{
    using (var context = CreateSqliteContext())
    {
        context.Works.Add(work);
        context.SaveChanges();
    }    
}

[Fact]
public void Post_InsertDuplicateWork_ShouldThrowException()
{
    var work1 = new Work { Name = "Test Work" };
    var work2 = new Work { Name = "Test Work" };

    Insert(work1);

    Action saveDuplicate = () => Insert(work2);

    saveDuplicate.Should().Throw<DbUpdateException>(); // Pass Ok
}
1
3/26/2019 5:19:47 PM


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