Unit tests assert vs Mockito.verify()

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.

  1. 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.

  2. 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.

  3. 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:

  1. 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.

  2. 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.

  3. 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.

  4. 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 verifying, 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.

Tags:

Java

Mockito