HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Entity Framework 7 In Memory Database - Unit Testing using xUnit

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
databasetestingusingmemoryunitxunitframeworkentity

Problem

I'm using EF7 with In-Memory database and xUnit for repository testing. I'd like to know if it's a good practice initializing the database in this manner for reuse it in every test method, specifically through the Initialize() method:

private Context _context;
private BrandsRepository _repository;
private void Initialize()
{
    var db = new DbContextOptionsBuilder();
    db.UseInMemoryDatabase();
    _context = new Context(db.Options);
    _repository = new BrandsRepository(_context);

    _context.Database.EnsureDeleted();
    _context.Database.EnsureCreated();
}

[Fact]
public void Retrieve_Brands()
{
    // Arrange
    Initialize();
    var brands = new List()
    {
        new Brand() { Name = "First" },
        new Brand() { Name = "Second" },
        new Brand() { Name = "Third" }
    };
    _context.Brands.AddRange(brands);
    _context.SaveChanges();

    // Act
    var retrievedBrands = _repository.GetAll();

    // Assert
    Assert.Equal(retrievedBrands, brands);
}

[Fact]
public void Add_a_Brand()
{
    // Arrange
    Initialize();
    var brand = new Brand() { Name = "First" };

    // Act
    _repository.Add(brand);

    // Assert
    Assert.Equal(_context.Brands.First(), brand );
}

Solution

I don't know xUnit, but in other testing frameworks you can reuse a single in-memory database in multiple test cases, by annotating the text cases (or rather, the entire test class) transactional. That is, the database manipulations within the test cases will be automatically rolled back after leaving the scope of the methods. That way tests can run faster, thanks to not recreating a full text database repeatedly. I would hope a similar concept exists in xUnit too, and research that.

If no such feature exists, your approach seems fine, but Initialize is a bit too generic of a name, I would call it RecreateDatabase instead to make it more clear what it does. Or, actually, other frameworks use annotation like @Before for this kind of purpose, instead of an explicit method call.

Lastly, the test in the second example is a bit weak. You only get that the first item is what you inserted. I suggest to either add a test to verify that there is only 1 item, or require it using GetAll like you did in the other test case.

Context

StackExchange Code Review Q#108784, answer score: 2

Revisions (0)

No revisions yet.