The Model Is Ready But No Data: Consider Mocking
I am sure you have encountered this scenario rather often especially in the early stages of a project: the model is present, the database was created but there is no test data.
![]() |
| "Oooooo! I’ll blast yall tables off with seed data varmints!" |
If we are using Entity Framework Code-First then we could seed data during the database initialization process. However, in the case that a DB initialization is not possible, the data could still be seeded following a different mechanism. Assuming that I was working on a system based on the Northwind database, and the database was empty then data could be seeded and the process is very simple:
public async Task SeedDataAsync()
{
if(!_context.Suppliers.Any())
{
var category = _context
.Categories
.FirstOrDefault(c => c.CategoryName.Equals("Beverages"));
if(category == null)
{
category = new Category
{
CategoryName = "Beverages",
Description = "Soft drinks, coffees, teas, beers, and ales"
};
}
var supplier = new Supplier
{
CompanyName = "Joe's One Stop",
ContactName = "Joe Marino",
Address = "123 Main St.",
City = "Ottawa",
Region = "ON",
PostalCode = "O6T 3P9",
Country = "Canada",
Phone = "613-555-1232",
HomePage = "www.a1mansoftware.com",
Products = new List<Product>
{
new Product() { ProductName = "Sasquatch Ale", QuantityPerUnit = "24 - 12 oz bottles", UnitPrice = 14.00m, UnitsInStock = 111, Category = category },
new Product() { ProductName = "Steeleye Stout", QuantityPerUnit = "24 - 12 oz bottles", UnitPrice = 18.00m, UnitsInStock = 20, Category = category },
new Product() { ProductName = "Laughing Lumberjack Lager", QuantityPerUnit = "24 - 12 oz bottles", UnitPrice = 13.50m, UnitsInStock = 52, Category = category }
}
};
if (category.CategoryID == 0 ) _context.Categories.Add(category);
_context.Suppliers.Add(supplier);
await _context.SaveChangesAsync();
}
}
then call it when the system initializes, or in a startup sequence like this:
seeder.SeedDataAsync().Wait();
I have not tested the above seed but it encapsulates the general idea.
Seeding data has its use and benefits because it allows to create a base data on which development can start and progress can be shown fairly quickly and the software development process shows advance.
However, there are scenarios where trying to seed data for the lack of it might be counterproductive and as a result we find ourselves losing perspective as to what the software we are building is trying to accomplish. To seed the needed data we dedicate massive amounts of time with the hope to get our development moving forward; data that at the end of the day is thrown away. Even when we have managed to seed data I have encountered scenarios where other developers have modified the data for one reason or another and now the feature under development or unit tests does not work anymore.
Mocking frameworks can help us abstract dependencies to a data access layer. Using mocking frameworks we can create these mock object which can be setup to provide data needed to develop and test a feature and never access the database.
Using mock objects also allows unit tests to isolate themselves, hence, the feature under development can be tested carefully.
In my previous note, Testing EF 6.x Async Queries With Moq: In Memory DbAsyncQueryProvider using mock objects allowed testing Task<IQueryable<CustomerOrderStatistic>> CustomerOrderSummaryAsync( CustomerOrderSearch criteria) without accessing the database because the data required for the method under test was provided by mocking repositories required by the service. Hence the development of the feature was done in isolation. Here are the tests that were designed and executed:
| Moq framework used to mock DbSet and repositories |
Conclusion
The take home message is that using mocking frameworks will force you to start developing a Unit Test infrastructure, and the benefits that we collect from such infrastructure are long lasting. For instance:- Mock objects helps greatly in a Test Driven Development process. It takes time and practice to develop a TDD state of mind.
- Test new features in isolation, helping test coverage.
- Abstract data access layer: the functionality can be tested without the need of seeded data.
- As a result of the above item; developing functionality which depends on the implementation of other dependencies can be undertaken because those dependencies can be mocked. (mocking repositories, the above unit tests does not need the implementation of repositories dependencies only their definitions.
- As a result of conclusion 2 and 3; good SOLID Object Oriented principles become pivotal hence if dependencies are very hard to mock then the original design start to release its own smell.
This post is not trying to say that seed data to help us develop new features is a bad thing. Seeding data has its own objectives and is a powerful tool at our disposal, however, we should not depend on seeded data to be able to develop new functionality : mocking framework and TDD together are great tools to consider.

No comments:
Post a Comment