Mockito in a nutshell

As introduced in Chapter 1, Retrospective on Software Quality and Java Testing, there are different levels of software testing, such as unit, integration, system, or acceptance. Regarding unit tests, they should be executed in isolation for a single piece of software, for example, an individual class. The objective in this level of tests is to verify the functionality of the unit and not of its dependencies.

In other words, we want to test what is known as the System Under Test (SUT) but not its Depended-On Components (DOCs). To achieve this isolation, we use typically test doubles to replace these DOCs. Mock objects are a kind of test double, which are programmed with expectations about the real DOC.

In few words, Mockito is a testing framework that allows mock object creation, stubbing, and verification. To that aim, Mockito provides an API to isolate the SUT and its DOCs. Generally speaking, using Mockito involves three different steps:

  1. Mocking objects: In order to isolate our SUT, we use the Mockito API to create mocks of its associated DOC(s). This way, we guarantee that the SUT is not depending on its real DOC(s), and our unit test is actually focused on the SUT.
  2. Setting expectations: The differential aspect of mocks object with respect to other test doubles (such as stub) is that mock objects can be programmed with custom expectations according to the needs of the unit test. This process in the Mockito jargon is known as stubbing methods, in which these methods belong to the mocks. By default, mock objects mimic the behavior of real objects. In practical terms, it means that mock objects return appropriate dummy values such as false for Boolean types, null for objects, 0 for integer or long return types, and so on. Mockito allows us to change this behavior with a rich API, which allows stubbing to return a specific value when a method is called.
When a mock object is not programmed with any expectation (that is, it has no stubbing method), technically speaking, it is not a mock object but a dummy object (take a look at Chapter 1, Retrospective on Software Quality and Java Testing for the definition).
  1. Verification: At the end of the day, we are creating tests, and thus, we need to implement some kind of verification for the SUT. Mockito provides a powerful API to carry out different types of verifications. With this API, we assess the interactions with the SUT and DOCs, verifying the invocation order with a mock, or capturing and verifying the argument passed to a stubbed method. Furthermore, the verification capabilities of Mockito can be complemented with the built-in assertion capabilities of JUnit or using a third-party assertion library (for example, Hamcrest, AssertJ, or Truth). See section Assertions within Chapter 3, JUnit 5 Standard Tests.

The following table summarizes the Mockito APIs grouped by the aforementioned phases:

Mockito API

Description

Phase

@Mock

This annotation identifies a mock object to be created by Mockito. This is used typically for DOC(s).

1.Mocking objects

@InjectMocks

This annotation identifies the object in which the mocks are going to be injected. This is used typically to the unit we want to test, that is, our SUT.

1.Mocking objects

@Spy

In addition to mocks, Mockito allows us to create spy objects (that is, a partial mock implementation, since they use the real implementation in non-stubbed methods).

1.Mocking objects

Mockito.when(x).thenReturn(y)

Mockito.doReturn(y).when(x)

These methods allow us to specify the value (y) that should be returned by the stubbed method (x) of a given mock object.

2.Setting expectations (stubbing methods)

Mockito.when(x).thenThrow(e)

Mockito.doThrow(e).when(x)

These methods allow us to specify the exception (e) that should be thrown when calling a stubbed method (x) of a given mock object.

2.Setting expectations (stubbing methods)

Mockito.when(x).thenAnswer(a)

Mockito.doAnswer(a).when(x)

Unlike returning a hardcoded value, a dynamic user-defined logic (Answer a) is executed when a given method (x) of the mock is invoked.

2.Setting expectations (stubbing methods)

Mockito.when(x).thenCallRealMethod()

Mockito.doCallRealMethod().when(x)

This method allows us the real implementation of a method instead the mocked one.

2.Setting expectations (stubbing methods)

Mockito.doNothing().when(x)

When using a spy, the default behavior is calling the real methods of the object. In order to avoid the execution of a void method x, this method is used.

2.Setting expectations (stubbing methods)

BDDMockito.given(x).willReturn(y)

BDDMockito.given(x).willThrow(e)

BDDMockito.given(x).willAnswer(a)

BDDMockito.given(x).willCallRealMethod()

Behaviour-driven development is a test methodology in which tests are specified in terms of scenarios and implemented as given (initial context), when (event occurs), and then (ensure some outcomes). Mockito supports this type of tests through the class BDDMockito. The behavior of the stubbed methods (x) is equivalent to Mockito.when(x).

2.Setting expectations (stubbing methods)

Mockito.verify()

This method verifies the invocation of mock objects. This verification can be optionally enhanced using the following methods:

  • times(n): The stubbed method is invoked exactly n times.
  • never(): The stubbed method is never called.
  • atLeastOnce(): The stubbed method is invoked at least once.
  • atLeast(n): The stubbed method is called at least n times.
  • atMost(n): The stubbed method is called at the most n times.
  • only(): A mock fails if any other method is called on the mock object.
  • timeout(m): This method is called in m milliseconds at the most.

3.Verification

Mockito.verifyZeroInteractions()

Mockito.verifyNoMoreInteractions()

These two methods verify that a stubbed method has no interactions. Internally, they use the same implementation.

3.Verification

@Captor

This annotation allows us to define an ArgumentChaptor object, aimed to verify the arguments passed to a stubbed method.

3.Verification

Mockito.inOrder

It facilitates verifying whether interactions with a mock were performed in a given order.

3.Verification

 

The use of the different annotations depicted in preceding the table (@Mock, @InjectMocks, @Spy, and @Captor) is optional, although it is recommendable for the shake of test readability. In other words, there are alternatives to the use of annotation using different Mockito classes. For instance, in order to create a Mock, we can use the annotation @Mock as follows:

@Mock
MyDoc docMock;

The alternative to this would be using the method Mockito.mock, as follows:

MyDoc docMock = Mockito.mock(MyDoc.class)

The following sections contains comprehensive examples using the Mockito APIs described in preceding table within Jupiter tests.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.37.196