3
\$\begingroup\$

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<Brand>()
    {
        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 );
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ I just found this in the documentation explaining it all. You should implement IDisposable and make use of Dispose(). \$\endgroup\$
    – Franco
    Commented Oct 26, 2015 at 14:40

1 Answer 1

2
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ Your answer was a guide, thanks. I'll continue like this. And yes, those names are very generic, I just was trying to make it work. \$\endgroup\$
    – Franco
    Commented Oct 27, 2015 at 0:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.