知識庫 / Spring / Spring Boot RSS 訂閱

在應用程序啓動前配置 @MockBean 組件

Spring Boot,Testing
HongKong
4
10:53 AM · Dec 06 ,2025

1. 簡介

<em @MockBean</em>> 是 Spring 框架提供的註解。它能夠創建一個 Spring Bean 的 mock 對象,允許我們在測試過程中將實際 Bean 替換為 mock 對象。這在集成測試中尤其有用,因為我們希望隔離某些組件,而無需依賴其實際實現。

在本教程中,我們將探討各種配置 <em @MockBean</em>> 組件的方法,以測試 Spring Boot 應用程序。

2. 早期配置的需求

配置 @MockBean 組件在應用程序啓動之前至關重要,當我們需要在測試過程中控制應用程序中某些 Bean 的行為時,尤其是在這些 Bean 與外部系統(如數據庫或 Web 服務)進行交互時。

早期配置的優勢:

  • 隔離測試:通過模擬其依賴項,有助於隔離待測試單元的行為
  • 避免外部調用:防止原始 Bean 否則會調用外部系統(如數據庫或外部 API)
  • 控制 Bean 行為:我們可以預定義模擬 Bean 的響應和行為,從而確保測試具有可預測性,並且不依賴於外部因素

3. 早期配置技術

我們首先將探討如何配置 @MockBean 組件,然後探索在應用程序啓動之前配置這些組件的各種方法。

3.1. 在測試類中直接聲明

這是最簡單的模擬 Bean 的方法。我們可以直接在測試類中的字段上使用 <em/>@MockBean</em/> 註解。 Spring Boot 會自動將實際 Bean 替換為模擬的 Bean,並在上下文中完成替換:

@SpringBootTest(classes = ConfigureMockBeanApplication.class)
public class DirectMockBeanConfigUnitTest {
    @MockBean
    private UserService mockUserService;

    @Autowired
    private UserController userController;

    @Test
    void whenDirectMockBean_thenReturnUserName(){
        when(mockUserService.getUserName(1L)).thenReturn("John Doe");
        assertEquals("John Doe", userController.getUserName(1L));
        verify(mockUserService).getUserName(1L);
    }
}

在這種方法中,Mock 無縫地替換了 Spring 上下文中真實的 Bean,從而允許依賴該 Bean 的其他 Bean 使用 Mock。 我們可以獨立地定義和控制 Mock,而無需影響其他測試。

3.2. 使用 @MockBean@BeforeEach 進行配置

我們可以使用 Mockito@BeforeEach 方法中配置 mock bean,確保它們在測試開始前可用。

當我們需要在較高層級配置某些 bean,例如 repository、service 或 controller – 這些 bean 不直接可測試或具有複雜的依賴關係時,這非常有用。

在集成測試中,組件通常相互依賴,@MockBean@BeforeEach 幫助創建一個受控環境,通過在每個測試的開始時隔離某些組件並模擬其依賴項,從而使我們能夠專注於正在測試的功能:

@SpringBootTest(classes = ConfigureMockBeanApplication.class)
public class ConfigureBeforeEachTestUnitTest {

    @MockBean
    private UserService mockUserService;

    @Autowired
    private UserController userController;

    @BeforeEach
    void setUp() {
        when(mockUserService.getUserName(1L)).thenReturn("John Doe");
    }

    @Test
    void whenParentContextConfigMockBean_thenReturnUserName(){
        assertEquals("John Doe", userController.getUserName(1L));
        verify(mockUserService).getUserName(1L);
    }
}

這種方法確保在每次測試之前,我們的模擬配置會被重置,這使其適用於隔離測試。

3.3. 使用 <em @Mockbean</em>> 在嵌套測試配置類中

為了使測試類更清晰,並重用 Mock 配置,我們可以將 Mock 設置移動到一個單獨的嵌套 配置 類中。我們需要使用 <em @Mockbean</em>> 標記該配置類。在該類中,我們實例化並配置 Mock:

@SpringBootTest(classes = ConfigureMockBeanApplication.class)
@Import(InternalConfigMockBeanUnitTest.TestConfig.class)
public class InternalConfigMockBeanUnitTest {
    @TestConfiguration
    static class TestConfig {

        @MockBean
        UserService userService;

        @PostConstruct
        public void initMock(){
            when(userService.getUserName(3L)).thenReturn("Bob Johnson");
        }
    }
    @Autowired
    private UserService userService;

    @Autowired
    private UserController userController;

    @Test
    void whenConfiguredUserService_thenReturnUserName(){
        assertEquals("Bob Johnson", userController.getUserName(3L));
        verify(userService).getUserName(3L);
    }

}

這種方法有助於測試類專注於測試,配置分離,從而更容易管理複雜的配置。

3.4. 使用 @Mockbean 在外部測試配置類中

當我們需要在多個測試類之間重用測試配置時,可以將測試配置外部化到一個單獨的類中。 類似於之前的做法,我們需要使用 @TestConfiguration 註解來標記配置類。 這允許我們創建一個專門用於測試的配置類,該類可以用於在 Spring 上下文中模擬或替換 Bean:

@TestConfiguration
class TestConfig {

    @MockBean
    UserService userService;

    @PostConstruct
    public void initMock(){
        when(userService.getUserName(2L)).thenReturn("Jane Smith");
    }
}

我們可以在我們的測試類中使用 @Import(TestConfig.class)導入此測試配置:

@SpringBootTest(classes = ConfigureMockBeanApplication.class)
@Import(TestConfig.class)
class ConfigureMockBeanApplicationUnitTest {

    @Autowired
    private UserService mockUserService;

    @Autowired
    private UserController userController;

    @Test
    void whenConfiguredUserService_thenReturnUserName(){
        assertEquals("Jane Smith", userController.getUserName(2L));
        verify(mockUserService).getUserName(2L);
    }
}

這種方法在我們需要配置多個測試組件或想要擁有可重用、可在不同測試用例之間共享的mock設置時非常有效。

3.5. 針對特定配置

當我們需要針對不同的配置方案進行測試,例如不同的環境(例如開發或測試環境),我們可以創建針對特定配置方案的配置。通過將 @ActiveProfiles 應用到我們的測試類上,我們可以為我們的測試需求加載不同的應用程序配置。

讓我們為我們的開發配置方案創建一個測試配置:

@Configuration
@Profile("Dev")
class DevProfileTestConfig {

    @MockBean
    UserService userService;

    @PostConstruct
    public void initMock(){
        when(userService.getUserName(4L)).thenReturn("Alice Brown");
    }
}

然後,我們可以將活動配置文件設置為“Dev”:

@SpringBootTest(classes = ConfigureMockBeanApplication.class)
@ActiveProfiles("Dev")
public class ProfileBasedMockBeanConfigUnitTest {

    @Autowired
    private UserService userService;

    @Autowired
    private UserController userController;

    @Test
    void whenDevProfileActive_thenReturnUserName(){
        assertEquals("Alice Brown", userController.getUserName(4L));
        verify(userService).getUserName(4L);
    }
}

這種方法在不同的環境中(如開發、測試或生產)進行測試時非常有用,可以確保我們模擬了特定用户畫像所需的精確條件。

3.6. 使用 Mockito 的 Answer 實現動態 Mock

當我們需要對 Mock 的行為進行更精細的控制,例如根據運行時輸入或條件動態更改響應時,可以使用 Mockito 的 Answer 接口。 這允許我們在測試開始前配置動態 Mock 的行為:

@SpringBootTest(classes = ConfigureMockBeanApplication.class)
public class MockBeanAnswersUnitTest {
    @MockBean
    private UserService mockUserService;

    @Autowired
    private UserController userController;

    @BeforeEach
    void setUp() {
        when(mockUserService.getUserName(anyLong())).thenAnswer(invocation ->{
            Long input = invocation.getArgument(0);
            if(input == 1L)
                return "John Doe";
            else if(input == 2L)
                return "Jane Smith";
            else
                return "Bob Johnson";
        });
    }

    @Test
    void whenDirectMockBean_thenReturnUserName(){
        assertEquals("John Doe", mockUserService.getUserName(1L));
        assertEquals("Jane Smith", mockUserService.getUserName(2L));
        assertEquals("Bob Johnson", mockUserService.getUserName(3L));

        verify(mockUserService).getUserName(1L);
        verify(mockUserService).getUserName(2L);
        verify(mockUserService).getUserName(3L);
    }
}

在此示例中,我們根據方法調用配置了動態響應,這使我們在複雜的測試場景中擁有更大的靈活性。

4. 測試策略與注意事項

  • 避免過度使用 Mock: 過度使用 @MockBean 可能會降低測試的有效性。理想情況下,我們應將 Mock 的使用限制在那些真正外部或難以控制的依賴項上(例如,外部 API 和數據庫)。
  • 使用 @TestConfiguration 進行復雜設置: 當我們需要配置更復雜的行為時,我們應該使用 @TestConfiguration,因為它允許我們更優雅地設置 Mock 並提供更好的高級配置支持。
  • 驗證交互: 除了設置返回值之外,驗證與 Mock 的交互也至關重要。 這確保了正確的 메서드가按預期被調用。

5. 結論

配置在應用程序啓動前使用 <em/>@MockBean</em/> 組件可以作為測試 Spring Boot 應用程序的寶貴策略,因為它允許我們對模擬的依賴項進行精細控制。

在本文中,我們學習了各種配置 Mock Bean 組件的方法。通過遵循適合我們測試的方法,並應用最佳實踐和測試策略,我們可以有效地隔離組件並在一個受控環境中驗證其行為。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.