You use mocking in order to “fool” a Java object to think that it communicates with other real objects. Meaning that we may emulate class's dependencies, but not instantiating real ones. By such a way, we may decouple a focus class from its dependencies.
When mocking dependencies, the inputs of test become much more controllable, and test outputs can be easily asserted. Or, in some cases, the dependencies are not available, then we may still implement test by mocking them.
In my impression, smart + lazy = efficient; So, choose a Java mock framework, like Mockito. It gives human-like syntax. Actually, it has been included in Spring boot test starter.
I think the mocking test is able to decouple the dependencies, and making a unit test possible.
Certainly, in another way around, we may need to see how classes together to interact with each other, i.e. an integrated test. In such a case, we may need to see the server on, at least a simulated servlet container (or servlet dispatcher), database connections. We may simulate an Http request and then trigger the servlet service on, fetching data set from the database, running the business logic, and making an HTTP response. By this way, we may confirm that for instance, a rest API may work as supposed when it moves to the production.
How to create static mock:
Mockito must be higher than 3.4; must include mockito-inline and mockito-core both;
<dependency>
<artifactId>mockito-core</artifactId>
<groupId>org.mockito</groupId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<scope>test</scope>
</dependency>
How to create Static Partial Mock:
Optional Answer to be used with mock(Class, Answer)
Answer can be used to define the return values of unstubbed invocations.
This implementation can be helpful when working with legacy code. When this implementation is used, unstubbed methods will delegate to the real implementation. This is a way to create a partial mock object that calls real methods by default.
try(var mockedInstant = Mockito.mockStatic(Instant.class, Mockito.CALLS_REAL_METHODS)){
counter = 0;
mockedInstant.when(Instant::now).thenAnswer(
new Answer<>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
counter++;
switch (counter)
{
case 1,2,3 -> {
return AutomatedActionTestData.instants[counter - 1];
}
default -> {
return invocation.callRealMethod();
}
}
}
});
The most widely used annotation in Mockito is @Mock. We can use @Mock to create and inject mocked instances without having to call Mockito.mock manually.
The MockStatic returns a closable resource, so we put it inside try-with-resource block, so as to automatically close it afterwards. Don't forget to put a full assignment here, otherwise you will see a compiling error.
@Before: running the annotated method, before each test method. We need to enable Mockito annotations before each test method.
Alternatively, we can enable Mockito annotations programmatically by invoking MockitoAnnotations.initMocks():
@Before
public void init() {
MockitoAnnotations.initMocks(this);
}
No comments:
Post a Comment