By Ashley Waldron
All of the source code for this series can be found in this repository. Specifically, the code used throughout this item can be found here and its corresponding test classes found here.
The ‘any()’ group of matchers
The any() group of matchers (any(), anyString(), etc.) should really only be used in circumstances where you don’t care what is passed to the mocked method because it’s irrelevant to the actual test. We’ll talk about when this might be in a later item but for now we have no good reason to use it. Used the way it is in the test we currently have is just laziness. But it’s a laziness that weakens the testcase and doesn’t protect us against potential bugs that could be introduced in the code.
For this item we’ll focus on the EmployeeNumberGenerator.generate() call. We’ve setup the mock as follows [See Item2UserServiceTest.createSuccessItem2Broken()]:
given(employeeNumberGenerator.generate(anyString())).willReturn("EUS1002");The problem with setting up mocks this way is that if we break the code by passing the wrong value into the EmployeeNumberGenerator.generate() method, for example (See Item2UserService):
userEntity.setEmployeeNumber(employeeNumberGenerator.generate("ThisIsABug"));Then this test will still pass (try it)!
Getting stricter with mocks
We only really have 2 choices to guard against the above defect
1. We could add an explicit verification to the assertions of the test, like:
then(employeeNumberGenerator).should().generate("US-EAST");2. We could just setup the mock in a less forgiving manner.
Although option 1 is perfectly valid, option 2 makes it obsolete because it’s less work for the same outcome. Also, there’s always a chance a developer might forget to add the assertion at the end. If we setup the mock in a less forgiving manner then the test will fail if there’s a bug which means that in cases like these the mock setup doubles as an assert.
If we now update the test to be more strict by demanding that the mock setup only works when the exact value we expect to be passed to it, is indeed passed to it we have (See Item2UserServiceTest.createSuccessItem2Fixed()):
given(employeeNumberGenerator.generate("US-EAST")).willReturn("EUS1002");When we run the test again we get something like the following error:

This now allows us to track down the defect and fix it.
Setting up mocks like this should be done wherever possible (which should be the majority of mock setups). You can see that when we use explicit mock setups like this they often double as verifications. This isn’t always true but it will mostly be the case. So doing it this way usually allows us to cut down on test code bloat since we don’t need to write a separate verification step for that method call or run the risk of forgetting to.
However it isn’t always possible to setup mocks in this less forgiving manner so we’ll look at that scenario in the next item.