The other day I was reading a little about Unit Testing and I saw some examples where people create a repository interface (i.e. IExampleRepository
) and then create the real repository (public class ExampleRepository : IExampleRepository
) and a repository to be used for unit testing (FakeExampleRepository : IExampleRepository
).
In the IExampleRepository
they were implementing the same methods as in the ExampleRepository
, however with different Linq queries.
What is exactly the objective here? I thought one part of unit testing your code is make sure that a method works correctly? But when I use two totally different queries, one for ‘real’ and one in the test, how much sense does the test make?
0
One of the aims of unit testing is to test just one thing at a time i.e. a single class and method. If the repository itself is not under test then you would normally mock this out in some way so as just to test the logic in your method/class.
That said you do also need to test with a ‘real’ repository*, but this would normally be done in an integration/system test
*obviously real as in repo set up for test, hopefully not e.g. the production DB.
7
I agree with the two answers from jk. and Jan Hudec — they give some really good information. But I thought I’d add a bit.
Your first question (“What exactly is the objective here?”) is important. In the case you’re describing, the real objective is to test the classes that are utilizing the IExampleRepository
interface, not testing the repository implementations. Creating the FakeExampleRepository
allows you to test those client classes without worrying about the details of the real repository class.
This is especially true if the object you’re trying to set up makes testing difficult (e.g. accesses the file system, calls a webservice, or talks to a database). By using interfaces (and other such techniques), you keep the coupling low. Therefore, class X
need only know about the interface and need not know about the implementation details. The goal is all about making sure that class X
is doing the right thing.
Mocking (or stubbing, faking… there are nuanced differences) is a powerful tool for unit testing and TDD. But it can be a pain to manually create and maintain these implementations. Therefore, most languages now have mocking libraries to help. Since you’re using C#, I’d recommend Moq because it is simple and very powerful. Then you can test against the interface without piling up extra code for the mock implementations.
2
What is exactly the objective here?
Isolation.
The idea of a unit test it to test the smallest possible unit of code. You do this by isolating it from all other production code in the test.
By creating fake classes the only production code is the class under test.
If you create a fake repository properly and the test fails you know that the issue is with the code-under-test. This gives you the benefit of diagnosis for free.
Have a look at isolation frameworks (like Moq as suggested by @Allan) to be able to generate these fakes quickly to setup test conditions and use them to assert against.
1
There are three reasons why you might want to provide mock instance to unit test:
- You want to limit the scope of the test, so that the test is not affected by bugs in the depndee, possibly because it is not finished yet or is not stable or you don’t want bugs in somebody else’s affect your tests.
- The dependee is complicated to set up. For example data access layer is often mocked out, because the real one requires setting up a test database. You still need to test the real data access layer, but you can limit the costly setup when debugging other things.
- To test that the dependent class properly reacts to various kinds of errors, you provide a mock version that returns all sorts of wrong answers. Because many failure modes are rather difficult to reproduce, but should still be tested.