The title is fairly self explanatory.
To elaborate: I’m currently updating a suite of unit tests for an application which makes heavy use of Entity Framework. We connect to this via a classic repository interface so it can be mocked out.
We’re not doing test first (that’s a whole different argument, which I don’t want this question to degenerate into). Rather a “code a bit, test a bit” sort of approach. So we’re not backfilling a whole application with tests, either.
I appreciate that a whole suite of tests for such an application is likely to require a very complex repository mock. However, I just created a new test class and the very first test required a mock repository with about 5 mocked out repository get/save functions.
It was a fairly simple function that was being tested. The range of mock classes were needed because of operations carried out in the class constructor and suchlike.
Having done so it struck me that that hardly looked like a unit. And that it might be a sign my code was too interdependent. So: is creating a single test that demands a complex mock often a sign of poor architecture?
2
I’m going to have to make a couple of guesses here
You mention EF so I’m guess the mocks in question are related to the datalayer?
Since you are using EF, I guess your Repository presents an IQueryable and your Models construct queries within themselves?
This would lead to you then having to craft you mock with data which is consistent with the various queries your Models run, which I imagine could end up being pretty complicated.
I think the mistake here is the queryable repository. My view is that repositories should expose methods such as
IEnumerable GetModelsByConditionXAndConditionY(var valueOfAParmeter)
rather than
IEnumerable GetModelsByQuery(Func SomeQueryFunction)
or
IQueryable GetModelsButDontReturnThemYetINeedToThink()
This enables you to construct an in memory version of your database with consistent test data, because the ways in which that data are returned are known by the Repository.
Any Consuming class can take the repository and be expected to work correctly without model specific setup of the data.
I also tend to make this mock repository as its own class rather than using a mock framework to configure it per unit test
This makes your unit tests pretty simple as they all use the same mock data and allows you to inject the same mock repositories into your real app for UI testing etc
2