Fiddling around with Mockito for implementing unit tests of my services but for some reason I can't get this through my thick skull. My tests are passing but I am not conviced that I am doing it right.
Here is an example where I test the count() method. The method simply forwards the call to its repository and I wan't to verify that only that and nothing else happens. This is what I've got:
@RunWith(MockitoJUnitRunner.class)
public class PersonServiceImplTest {
@Mock
private PersonRepository personRepository;
@InjectMocks
private PersonServiceImpl personService;
@Test
public void testCount() {
when(personRepository.count()).thenReturn(2L);
long count = personService.count();
assertEquals(2L, count);
verify(personRepository).count();
}
}
My test is passing but I have some questions.
Is the assertEquals needed? as I understand it, whatever I put as the expected result of the method stub (.thenReturn(value..)) will ALWAYS be the value returned. Or could it be something else in this scenario?
Do I need the verify? I feel like I do because I want to verify that personRepository.count() was actually called. Or is that redundant when I have assertEquals() as well?
Do I need both assertEquals and verify?
And finally, am I doing this right :)
Thank you
The Assert command is used to validate critical functionality. If this validation fails, then the execution of that test method is stopped and marked as failed. In the case of Verify command, the test method continues the execution even after the failure of an assertion statement.
JUnit has a broader approval, being mentioned in 65 company stacks & 54 developers stacks; compared to Mockito, which is listed in 9 company stacks and 6 developer stacks.
In the case of the “Assert” command, as soon as the validation fails the execution of that particular test method is stopped. Following that the test method is marked as failed. Whereas, in the case of “Verify”, the test method continues execution even after the failure of an assertion statement.
Asserts are used to validate that properties of your system under test have been set correctly, whereas Verify is used to ensure that any dependencies that your system under test takes in have been called correctly.
Yes, you are doing it right.
You are injecting a mock repository into a real service, then testing the service. When it comes to business logic in your service, anything could be happening. That's why it's important to verify the code with known inputs and known outputs, just like you're doing.
You're checking the result of the business logic, given the response from the repository. This particular code is fairly straightforward, but imagine if the business logic was providing an average or a sum, not just the same value provided from the repository.
and 3. The verify and the assertEquals are testing different things. The verify checks that your repository method was called, the assert checks that the service responded with the correct value. Imagine that your service method had a hard-coded return 2L
. The assertEquals would pass, but the verify would fail.
Yes, you're doing it right. What you're testing is linked to Why you're testing. Whether a particular assertion or verify is required is usually down to the individual situation. In this case, there is little point in testing that your repository method returns 2L
, but there is a good case for testing that your service returns 2L
. Similarly, there is no point in testing that the service method has been called, but there's a good case for testing that the repository method has been called.
You now have the tools to test your service, the next step is determining which tests to write.
In order:
Is the assertEquals()
needed: It depends. Is there anything done to the result of personRepository.count()
in personService
before it is returned, that has any possibility of changing its value? If the answer is "definitely not", then you might not need to assertEquals()
- but if there's any chance something might go wrong, then assertEquals()
will make sure it didn't.
Do you need verify()
: It depends. Is there any chance that personRepository.count()
wasn't called? Or that it was called more than once (verify()
by default expects its argument to be called exactly once)? If not, then you might not need it.
Do you need both: It depends (noticing a pattern?). See above: they do different things. There are many cases in which you want both things to be checked: 1. that the right result is returned, and 2. that the result is returned by doing the things you expect to be done.
Are you doing this right: Well... It depends. Does personRepository.count()
look like
public int count() {
return this.personService.count();
}
If so, you probably don't need much testing for it at all. If you insist on having a test, skipping verify()
is probably alright, because the method above has no other way of getting a value than by calling the function you would be verify
ing, and it returns that value, so it could hardly call it more than once.
On the other hand, if your function looks like:
public int count() {
// get a personService from an injector
// log the personService's details
// generate a random number
// try calling count() on personService, catch an error
// if you caught the error, return the random number
}
Then maybe you do want to verify()
because all of a sudden, there are a lot of things going on and some of them (i.e. the random number) could be confused for correct functioning even if something is going horribly wrong.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With