Created
March 5, 2018 22:34
-
-
Save zverbatim/28fe90c86f2555fb6e78816a3d200413 to your computer and use it in GitHub Desktop.
Difference between @mock, @MockBean and Mockito.mock()
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Source : https://stackoverflow.com/questions/44200720/difference-between-mock-mockbean-and-mockito-mock | |
Plain Mockito library | |
import org.mockito.Mock; | |
... | |
@Mock | |
MyService myservice; | |
and | |
import org.mockito.Mockito; | |
... | |
MyService myservice = Mockito.mock(MyService.class); | |
come from the Mockito library and are functionally equivalent. | |
They allow to mock a class or an interface and to record and verify behaviors on it. | |
The way using annotation is shorter, so preferable and often preferred. | |
Note that to enable Mockito annotations during test executions, the MockitoAnnotations.initMocks(this) static method has to be called. | |
To avoid side effect between tests, it is advised to do it before each test execution : | |
@Before | |
public void initMocks() { | |
MockitoAnnotations.initMocks(this); | |
} | |
Another way to enable Mockito annotations is annotating the test class with @RunWith by specifying the MockitoJUnitRunner that does this task and also other useful things : | |
@RunWith(org.mockito.runners.MockitoJUnitRunner.class) | |
public MyClassTest{...} | |
Spring Boot library wrapping Mockito library | |
This is indeed a Spring Boot class: | |
import org.springframework.boot.test.mock.mockito.MockBean; | |
... | |
@MockBean | |
MyService myservice; | |
The class is included in the spring-boot-test library. | |
It allows to add Mockito mocks in a Spring ApplicationContext. | |
If a bean, compatible with the declared class exists in the context, it replaces it by the mock. | |
If it is not the case, it adds the mock in the context as a bean. | |
Javadoc reference : | |
Annotation that can be used to add mocks to a Spring ApplicationContext. | |
... | |
If any existing single bean of the same type defined in the context will be replaced by the mock, if no existing bean is defined a new one will be added. | |
When use classic/plain Mockito and when use @MockBean from Spring Boot ? | |
Unit tests are designed to test a component in isolation from other components and unit tests have also a requirement : being as fast as possible in terms of execution time as these tests may be executed each day dozen times on the developer machines. | |
Consequently, here is a simple guideline : | |
As you write a test that doesn't need any dependencies from the Spring Boot container, the classic/plain Mockito is the way to follow : it is fast and favors the isolation of the tested component. | |
If your test needs to rely on the Spring Boot container and you want also to add or mock one of the container beans : @MockBean from Spring Boot is the way. | |
Typical usage of Spring Boot @MockBean | |
As we write a test class annotated with @WebMvcTest (web test slice). | |
The Spring Boot documentation summarizes that very well : | |
Often @WebMvcTest will be limited to a single controller and used in combination with @MockBean to provide mock implementations for required collaborators. | |
Here is an example : | |
import org.junit.Test; | |
import org.junit.runner.RunWith; | |
import org.mockito.Mockito; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; | |
import org.springframework.boot.test.mock.mockito.MockBean; | |
import org.springframework.http.MediaType; | |
import org.springframework.test.context.junit4.SpringRunner; | |
import org.springframework.test.web.servlet.MockMvc; | |
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; | |
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | |
@RunWith(SpringRunner.class) | |
@WebMvcTest(FooController.class) | |
public class FooControllerTest { | |
@Autowired | |
private MockMvc mvc; | |
@MockBean | |
private FooService fooServiceMock; | |
@Test | |
public void testExample() throws Exception { | |
Foo mockedFoo = new Foo("one", "two"); | |
Mockito.when(fooServiceMock.get(1)) | |
.thenReturn(mockedFoo); | |
mvc.perform(get("foos/1") | |
.accept(MediaType.TEXT_PLAIN)) | |
.andExpect(status().isOk()) | |
.andExpect(content().string("one two")); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment