1. 概述
在本快速教程中,我們將探討三種使用 Mockito 和 Spring mocking 支持創建模擬對象的不同方法。我們還將討論它們之間的差異。
2. Mockito.mock()
該 Mockito.mock() 方法允許我們創建類或接口的 Mock 對象。
我們可以使用 Mock 對象來為它的方法設置返回值,並驗證這些方法是否被調用。
以下是一個示例:
@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockedValueReturned() {
UserRepository localMockRepository = Mockito.mock(UserRepository.class);
Mockito.when(localMockRepository.count()).thenReturn(111L);
long userCount = localMockRepository.count();
Assert.assertEquals(111L, userCount);
Mockito.verify(localMockRepository).count();
}在使用此方法之前,我們無需對其進行任何其他操作。我們可以使用它來創建模擬類字段,以及在方法中創建本地 Mock。
3. Mockito 的 <em @Mock@ 註解
此註解是 <em Mockito.mock() 方法的簡寫。需要注意的是,我們應該僅在測試類中使用它。與 <em mock() 方法不同,使用此註解需要啓用 Mockito 註解。
我們可以通過以下方式進行操作:使用 <em MockitoJUnitRunner 運行測試,或者顯式調用 <em MockitoAnnotations.initMocks() 方法。
讓我們以使用 <em MockitoJUnitRunner 的方式為例:
@RunWith(MockitoJUnitRunner.class)
public class MockAnnotationUnitTest {
@Mock
UserRepository mockRepository;
@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
Mockito.when(mockRepository.count()).thenReturn(123L);
long userCount = mockRepository.count();
Assert.assertEquals(123L, userCount);
Mockito.verify(mockRepository).count();
}
}除了使代碼更易於閲讀之外,<em@Mock還便於在出現故障時查找mock對象,因為字段名會在故障信息中出現:
Wanted but not invoked:
mockRepository.count();
-> at org.baeldung.MockAnnotationTest.testMockAnnotation(MockAnnotationTest.java:22)
Actually, there were zero interactions with this mock.
at org.baeldung.MockAnnotationTest.testMockAnnotation(MockAnnotationTest.java:22)
此外,當與@InjectMocks一起使用時,它還可以顯著減少設置代碼量。
4. Spring Boot 中的 <em @MockBean</em> 註解
我們可以使用 <em @MockBean</em>> 來向 Spring 應用上下文添加 Mock 對象。 Mock 對象將替換上下文中的同類型現有 Bean。
如果未定義同類型的 Bean,則會添加一個新的 Bean。 此註解在集成測試中非常有用,其中特定的 Bean(例如外部服務)需要被 Mock。
要使用此註解,我們需要使用 <em SpringRunner</em>> 運行測試:
@RunWith(SpringRunner.class)
public class MockBeanAnnotationIntegrationTest {
@MockBean
UserRepository mockRepository;
@Autowired
ApplicationContext context;
@Test
public void givenCountMethodMocked_WhenCountInvoked_ThenMockValueReturned() {
Mockito.when(mockRepository.count()).thenReturn(123L);
UserRepository userRepoFromContext = context.getBean(UserRepository.class);
long userCount = userRepoFromContext.count();
Assert.assertEquals(123L, userCount);
Mockito.verify(mockRepository).count();
}
}當我們對字段使用註解時,mock 會被注入到該字段中,同時也會在應用程序上下文中進行註冊。
這一點在上面的代碼中可以明顯看出。我們使用了注入的 UserRepository mock 來模擬 count 方法。 然後我們使用來自應用程序上下文的 Bean 來驗證它確實是模擬的 Bean。
5. 結論
在本文中,我們探討了創建模擬對象的三種方法的差異,以及如何利用每種方法。