Get startedGet started for free

Verification in mocking

1. Verification in mocking

Welcome back! Now let's discuss a new way to verify tests that use mocks.

2. Motivation: No return values

Let's start with a common scenario. Previously, we tested methods by checking their return values. But what if there are no return values? What if the method is doing something (e.g. saving information somewhere) and the return values are not important? This is commonly the case with databases.

3. Example: Databases

A database is a digital system for storing, managing, and securing organized data. There are many providers, but this is material for a different course. Software systems use separate database servers because they are reliable and secure, have unlimited capacity, and the data stored inside can survive outages and shutdowns. However, because of their size and complexity, it's not practical to include databases in unit tests, which should stay fast and lightweight.

4. Example: Log messages

Suppose we are processing log messages and saving them to a database. Info messages go to `InfoStore`, errors to `ErrorStore`. Then the class that does this can look something like this. There are two member variables, `InfoStore` and `ErrorStore`. Our method `saveMessage()` takes a String message and returns nothing. It sends errors to `ErrorStore`, everything else to `InfoStore`.

5. InfoStore and ErrorStore

As we saw earlier, when creating mocks, the real classes don’t matter. For this demo, we will need only the most basic interfaces, or blueprints, for `InfoStore` and `ErrorStore`.

6. Mockito verify

So how can we test that a message was saved without creating any databases? To assert a mock was used, import Mockito verify. To assert a mock was not used, import Mockito verifyNoInteractions. Let's now see them in action.

7. Test setup

We begin by creating mocks for `ErrorStore` and `InfoStore`, and passing the mock objects to the constructor for MessageProcessor. Then, we create an example message and pass it to the saveMessage method. Finally, instead of using JUnit assertions, we use the mocks themselves to assert. We verify `infoStore` saves our message. We also verify the `errorStore` mock was never used.

8. Test failure messages

Let's pass a message that doesn't match expectations. A message like the one which starts with ERROR will not end up in the `InfoStore`. Then we will see the test fail with a message like: "Wanted but not invoked", notifying us which method call the mock expected.

9. Further verification tricks

Suppose we are sending not one message, but a list of messages, and we have a method saveMessageList that can process them one by one. We want to see where these messages went. We can do that by importing Mockito times. Then we can explicitly assert on how many times each mock was invoked. For example, we send three info messages. With Mockito's `times`, we can assert the `infoStore` save was used three times.

10. Let's practice!

Let's now practice verifying mock invocations!

Create Your Free Account

or

By continuing, you accept our Terms of Use, our Privacy Policy and that your data is stored in the USA.