Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing and too many mocks

I'm starting to practice TDD in my project, as a background it also contains legacy code. We use Mockito as a mocking framework and follow a Spring MVC approach.

There are times when there's a Service class implemented with many different DAO objects as @Autowired properties. There are simple methods within these services, like for example completeTransaction.

completeTransaction will use many of the DAO objects to complete its responsibilities

  • Update and save the transaction
  • Advance a business process
  • Closing other pending operations

However, in performing those operations, the method requires calls to different DAO to fetch and update the transaction, fetch a business process ID, fetch pending transactions (and save their updates). This means that unit testing this method makes me add many @Mock properties. And I need to set up the mock objects before the test will actually finish for me to test a certain condition.

This seems like a code smell, and to me it almost feels like the test is ensuring the implementation of the code instead of just its contract. Again, without mocking the dependencies, the test case will not run (due to NPE and others).

What is a strategy that I can follow to clean up code like this? (I can't really provide the actual source code on the question though). I'm thinking that one possibility would be to set up a facade class with methods like ("getPendingOperations" and "advanceBusinessProcess"). Then I can mock a single dependency. But then I figure that in all other classes that have situations like this I would need to do the same, and then I'm afraid to end up with a lot of "helper" classes just for the sake of cleaner tests.

Thank you in advanced.

like image 720
Jaime Garcia Avatar asked Oct 21 '22 16:10

Jaime Garcia


1 Answers

I think you'll want to do two things in general when you find yourself with too many mocks. These are not necessary easy, but you may find them helpful.

1) Try and make your methods and classes smaller. I think Clean Code says there are two rules, that classes should small. And that classes should be smaller then that. This makes some sense because as the units you are testing (methods and classes) get smaller, so will the dependencies. You will of course end up with more tests, but they will have less setup in each test.

2) Look at the Law of Demeter (https://en.wikipedia.org/wiki/Law_of_Demeter). There are a bunch of rules, but basically, you want to avoid long string of property/method calls. objA = objB.propertyA.SomeMethod().propertyC; If you need to mock out all of these objects just to get objA, the you will have a lot of setup. But if you can replace this with objA = objB.newProperty; then you only need to mock objB and it's one property.

Neither of these are silver bullets, but hopefully you can use some of these ideas with your project.

like image 91
ansible Avatar answered Oct 23 '22 10:10

ansible