I have a class which is refactored in 1 main class and 2 smaller classes. The main classes use the database (like a lot of my classes do) and sends an email.
So the main class has an IPersonRepository
and an IEmailRepository
injected which in his turn sends to the 2 smaller classes.
Now I want to unit test the main class, and have learned not to unittest the internal workings of the class, because we should be able to change the internal workings without breaking unit tests.
But as the class uses the IPersonRepository
and an IEmailRepository
, I HAVE to specify (mock / dummy) results for some methods for the IPersonRepository
. The main class calculates some data based on existing data and returns that. If I want to test that, I don't see how I can write a test without specifying that the IPersonRepository.GetSavingsByCustomerId
returns x. But then my unit test 'knows' about the internal workings, because it 'knows' which methods to mock and which not.
How can I test a class which has injected dependencies, without the test knowing about the internals?
background:
In my experience lots of tests like this create mocks for the repositories and then either provide the right data for the mocks or test if a specific method was called during execution. Either way, the test knows about the internals.
Now I've seen a presentation about the theory (which I've heard before) that the test should not know about the implementation. First because you are not testing how it works, but also because when you now change the implementation all unit tests fail because they 'know' about the implementation. While I like the concept of the tests being unaware of the implementation, I don't know how to accomplish it.
IPersonRepository
object, that interface and all the methods it describes are not "internal" any more, so it is not really a problem of the test. Your real question should be "how can I refactor classes into smaller units without exposing too much in public". The answer is "keep those interfaces lean" (by sticking to the interface seggregation principle, for example). That is IMHO point 2 in @DavidArno's answer (I guess there is no need for me to repeat that in another answer).