Mocks are simulated objects that mimic the behavior of real objects in controlled ways. OpenMRS 1.9 finally includes Mockito which is a library designated for creating mocks dynamically. In this document we will present how to use them in the context of OpenMRS. The presented code works in OpenMRS 1.9.9+.
It is best illustrated by an example. Let's rewrite org.openmrs.EncounterTest.setProvider_shouldSetExistingProviderForUnknownRole() using mocks. The test makes sure that a provider with the unknown role will be set for the given person when calling org.openmrs.Encounter.setProvider(Person).
The problem with this test is that Encounter.setProvider(Person) calls EncounterService.getEncounterRoleByUuid(String) and ProviderService.getProvidersByPerson(Person), both of which require the presence of the Spring Application Context and the database running. In the effect we are forced to write a heavy component test rather than a quick unit test. Mocks will allow us to go around this issue by stubbing the two methods.
First, we will modify the class declaration and members. We will get rid of BaseContextSensitiveTest which is responsible for setting up the Spring Application Context and the database. We will extend BaseContextMockTest instead, which provides support for @Mock annotations. We will also mock EncounterService and ProviderService by adding them as private members with @Mock annotation.
Finally, we will change the test to use mocked services.
See complete example here: https://github.com/openmrs/openmrs-core/blob/master/api/src/test/java/org/openmrs/EncounterTest.java
Mocking in Spring Context
It is also possible to use @Mock in tests running in the Spring context. The @Mock annotation is recognized in all test classes extending BaseContextSensitiveTest. You can use @Mock to mock out certain services and @Spy to spy on services.
Mocking Context outside BaseContextSensitiveTest
If you see an error like this:
It means that you called initMocks using static method import in your test. The fix is simply to use MociktoAnnotations.initMocks(this) instead of initMocks(this) or remove initMocks(this) and rely on BaseContextSensitiveTest calling it.