Unit Testing – MockRepository vs Test Database for Unit Testing

tddunit testingunit-of-work

Before starting, this question is not the same as this one.

Comming from a PHP background, my experience is in CakePHP, which is a framework that supports Unit Testing by setting up a local test database, handled by special classes called fixtures (let's you CRUD data on the test db before each test suite via code).

However, being new at .NET framework, intermediate tutorials suggest the use of Unit of Work pattern, in order to either use a real repository or a mock repository via an interface.

When it comes to unit testing, there isn't much difference between this 2 ways of handling data operation, but the issue I encountered was when loading relational data, as the real repository uses the framework's ORM while the mock repository use something similar to a List interface implementation to keep data in memory, and it isn't able to eager load nor lazy load relational data.

Up to this point I see 2 possible reason I stepped onto this issue:

  1. The mock repository should be coded so that it can somehow get relational data.
  2. I shouldn't be testing whether the model acquired related data, but test only whether the controller was able to acquire the main model from repository.

I'd like to know which of the 2 above would be it (or if maybe there's a 3rd one…) and the advantages/disadvantages of mock repository vs test db.

Best Answer

Given a scenario, when some method is called the data must be persisted into db and have following steps:

  1. Setup empty db simulator (you call it mock) and pass it in as a dependency
  2. do call the method you are testing
  3. Verify the data was stored in simulator

OR

  1. Setup db simulator with predefined data and pass it in as a dependency
  2. do call the method you are testing
  3. Verify the method operates properly on the data retrieved from simulator

Can you clarify which scenario you are having troubles with with relational data. It is whether persisted into simulator or retrieved from it.

If you are testing the logic that happens in your data layer you will end up testing the test code (mock setup specifically) and not the real system - such tests are to be avoided as they bring no value.

For example if you have a trigger that adds a log entry on update operation and you want to write the test that updates a record and checks for new log entry, there is no way to unit test that. You must not rely on mock to do that for you. Write integration/functional tests against real system instead.

Related Topic