Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've been doing TDD for year now, I feel pretty good about it, I love my test suites and all. However I've noticed that lately I've been doing a lot of mock call verification. For example I'd have a Service that will have a Repository injected - in my unit test I'd pass a mock of the Repository and verify that it was called within the method that I'm testing. I'd then check if the results returned are correct (in another test). This definitely "feels" wrong, since my unit tests are now very coupled to the implementation details. I've heard that you should test "behavior", however in a lot of the situations that's ... emm - not possible ? If you have a void method for example, you usually test side-effects. I mean it's easy to go ahead and show some simple code-kata's where this can be demonstrated, but IMHO it doesn't reflect very well to the real world programs that we write. Is what I'm doing wrong? Is this type of testing sort of an anti-pattern? I'd appreciate your opinion on this, I'm still a bit of a newbie when it comes to TDD.

share|improve this question
2  
Short answer: yes. There are very interesting questions about this topic already somewhere here. Your unit tests should not be fragile and depend heavily on your implementation. This is why higher level tests are for (integration, etc.). Here: programmers.stackexchange.com/questions/198453/… –  Kemoda Jul 4 '13 at 6:46
    
@Kemoda I'd appreciate it if you can link me to a discussion or some further material on this, I'd very much like to improve my techniques. –  Dimitar Dimitrov Jul 4 '13 at 6:48
1  
you have this for instance programmers.stackexchange.com/questions/198453/… i ll find other links later –  Kemoda Jul 4 '13 at 6:51

3 Answers 3

up vote 4 down vote accepted

Well, you should be trying to test inputs and outputs. You should be verifying externally visible behavior. The "promises" or "contract" that your class makes.

At the same time sometimes there's no better way to test a method than to do what you said.

I do think that it makes your test more brittle, so you should avoid tests that rely on implementation details if you can, but it's not an all-or-nothing deal. It's OK sometimes, the worst thing that happens is you change the implementation and have to update the test.

share|improve this answer

The purpose of a test is to restrict the possible productive implementations. Make sure that you only put restrictions on the implementation that you actually need. Typically this is what your program should do, and not how it does it.

So if for example your service adds something to the repository, you should test that the new entry is contained in the repository afterwards, and not that the add action is triggered.

For this to work, you need to be able to use the repository implementation (tested elsewhere) in the test of the service. I found that using the real implementation of a collaborator is generally a good approach – because it is really the best implementation around.


"So but what if using the real implementations in the test is expensive (e.g. because they require resources which are complicated to set up)? I need to use mocks in this case, right?"

In any case you'd probably want one integration test which tests that the real implementations work together. Make sure that this one integration test is all that is needed to test your service. Or in other words: If a service plugs together a lot of collaborators (and is hence potentially hard to test), make sure that it doesn't contain any logic. If it does, and you'd need multiple (integration) tests, you need to change the structure of your code, e.g. by isolating the logic and hence making it more testable.

Using mocks in this case eases the pain of testing a piece of badly isolated logic, and hence hides an architectual problem. So don't use mocks to test badly structured code, but fix the structure instead.

share|improve this answer
1  
I see what you're saying. This topic is a bit confusing as to "how much testing is too much testing", let's say I have an "aggregate service" that basically is a facade and just "glues" together bunch of other services/repositories/components what kind of tests do you write for it ? All I can think of is call verification. I hope I'm making sense. –  Dimitar Dimitrov Jul 4 '13 at 8:54

My thoughts re: 'aggregate services'.

Call verification will do this, but won't provide much value. You're just checking your wiring.

There are 3, non-exclusive, other ways to this:

  1. Extend the tests you have for each individual service so that it checks the higher level behaviour. For instance, if your hitting an in-memory database in your unit tests of the service, take it up a level so you're testing the service against an actual db. The service layer is higher up the abstraction tree, and so should your test.

  2. Use code generation to create the service directly from the aggregated services.

  3. Use some sort of reflection or dynamic language to do the same thing. For example, in Java, it may be possible to use a groovy interface, which passes the call on directly.

There are probably other ways to do this, but just checking wiring has very low pay back, and will hard wire you in to this implementation.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.