問題描述
在創(chuàng)建測試和模擬依賴時(shí),這三種方法有什么區(qū)別?
When creating tests and mocking dependencies, what is the difference between these three approaches?
@MockBean:
@MockBean:
@MockBean
MyService myservice;
@Mock:
@Mock:
@Mock
MyService myservice;
Mockito.mock()
Mockito.mock()
MyService myservice = Mockito.mock(MyService.class);
推薦答案
Plain Mockito 庫
import org.mockito.Mock;
...
@Mock
MyService myservice;
和
import org.mockito.Mockito;
...
MyService myservice = Mockito.mock(MyService.class);
來自 Mockito 庫并且在功能上是等效的.
它們?cè)试S模擬類或接口并記錄和驗(yàn)證其行為.
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.
請(qǐng)注意,要在測試執(zhí)行期間啟用 Mockito 注釋,MockitoAnnotations.initMocks(this)
靜態(tài)方法必須被調(diào)用.
為避免測試之間的副作用,建議在每次測試執(zhí)行之前進(jìn)行:
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);
}
啟用 Mockito 注釋的另一種方法是使用 @RunWith
注釋測試類,方法是指定執(zhí)行此任務(wù)的 MockitoJUnitRunner
以及其他有用的東西:
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{...}
<小時(shí)>
Spring Boot 庫封裝了 Mockito 庫
這確實(shí)是一個(gè) Spring Boot 類:
import org.springframework.boot.test.mock.mockito.MockBean;
...
@MockBean
MyService myservice;
該類包含在 spring-boot-test
庫中.
The class is included in the spring-boot-test
library.
它允許在 Spring ApplicationContext
中添加 Mockito 模擬.
如果上下文中存在與聲明的類兼容的 bean,它會(huì)將其替換為 mock.
如果不是這種情況,它將在上下文中添加模擬作為 bean.
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 參考:
Javadoc reference :
可用于向 Spring 添加模擬的注解應(yīng)用程序上下文.
Annotation that can be used to add mocks to a Spring ApplicationContext.
...
如果上下文中定義了任何現(xiàn)有的相同類型的單個(gè) bean將被模擬替換,如果沒有現(xiàn)有的 bean 被定義一個(gè)新的將被添加.
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.
<小時(shí)>
何時(shí)使用經(jīng)典/純 Mockito 以及何時(shí)使用 Spring Boot 中的 @MockBean
?
單元測試旨在獨(dú)立于其他組件來測試一個(gè)組件,并且單元測試還有一個(gè)要求:在執(zhí)行時(shí)間方面盡可能快,因?yàn)檫@些測試可能每天在開發(fā)人員機(jī)器上執(zhí)行數(shù)十次.
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.
因此,這是一個(gè)簡單的指南:
Consequently, here is a simple guideline :
當(dāng)您編寫不需要來自 Spring Boot 容器的任何依賴項(xiàng)的測試時(shí),經(jīng)典/普通的 Mockito 是遵循的方式:它速度快并且有利于被測試組件的隔離.
如果您的測試需要依賴 Spring Boot 容器并且您還想添加或模擬容器 bean 之一:Spring Boot 中的 @MockBean
就是這樣.
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.
Spring Boot的典型用法@MockBean
當(dāng)我們編寫一個(gè)帶有 @WebMvcTest
注釋的測試類(網(wǎng)絡(luò)測試切片)時(shí).
As we write a test class annotated with @WebMvcTest
(web test slice).
Spring Boot 文檔 很好地總結(jié)了這一點(diǎn):
The Spring Boot documentation summarizes that very well :
@WebMvcTest
通常會(huì)被限制在單個(gè)控制器中并用于結(jié)合 @MockBean
提供模擬實(shí)現(xiàn)需要的合作者.
Often
@WebMvcTest
will be limited to a single controller and used in combination with@MockBean
to provide mock implementations for required collaborators.
這是一個(gè)例子:
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"));
}
}
這篇關(guān)于@Mock、@MockBean 和 Mockito.mock() 之間的區(qū)別的文章就介紹到這了,希望我們推薦的答案對(duì)大家有所幫助,也希望大家多多支持html5模板網(wǎng)!