Spring Boot Test 的詳細使用教程

gongchengship發表於2024-11-12

Spring Boot Test 是 Spring Boot 提供的一個強大測試框架,用於幫助開發者簡化和加速應用程式的單元測試和整合測試。下面是對 Spring Boot Test 各種測試型別和主要註解的詳細教程。

1. Spring Boot Test 的基礎概念

Spring Boot 提供了多種不同層次的測試工具,主要分為以下幾類:

  • 單元測試:用於測試單個類的功能,通常會隔離外部依賴,使用 Mockito 等框架來模擬。
  • 整合測試:測試多個元件協同工作的情況,通常會啟動部分或全部 Spring 上下文。
  • 端到端測試:測試完整的應用,包括資料庫等所有依賴。

Spring Boot Test 框架的核心依賴是 spring-boot-starter-test,它包含了多種測試框架,如 JUnit、Mockito、AssertJ、Hamcrest 和 JSONassert 等。

2. Spring Boot Test 常用註解

2.1 @SpringBootTest

@SpringBootTest 是 Spring Boot 提供的核心註解,適用於大多數整合測試。它可以啟動完整的 Spring 上下文,模擬一個真實的應用程式環境。

示例:

@SpringBootTest
public class MyApplicationTests {

    @Autowired
    private SomeService someService;

    @Test
    public void testServiceMethod() {
        assertNotNull(someService);
    }
}

常用屬性:

  • classes:指定要載入的應用上下文類,通常是主應用類。
  • webEnvironment:指定 Web 環境型別,可以是 NONEMOCKRANDOM_PORTDEFINED_PORT

例如,如果我們要在隨機埠啟動 Web 伺服器:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WebApplicationTests {
    // 測試程式碼
}

2.2 @MockBean 和 @SpyBean

@MockBean@SpyBean 是 Spring Boot 提供的兩個註解,允許你在測試時模擬和監控 Bean 行為。@MockBean 可以模擬依賴,而 @SpyBean 則會部分使用真實物件。

示例:

@SpringBootTest
public class MyServiceTests {

    @MockBean
    private SomeDependency someDependency;

    @Autowired
    private SomeService someService;

    @Test
    public void testSomeMethod() {
        when(someDependency.someMethod()).thenReturn("mocked result");
        assertEquals("mocked result", someService.someMethod());
    }
}

2.3 @DataJpaTest

@DataJpaTest 是專門為 JPA 相關測試提供的註解。它會配置一個記憶體資料庫(如 H2),並只載入與 JPA 相關的 Bean。

示例:

@DataJpaTest
public class UserRepositoryTests {

    @Autowired
    private UserRepository userRepository;

    @Test
    public void testSaveAndFind() {
        User user = new User("testUser");
        userRepository.save(user);
        User foundUser = userRepository.findByUsername("testUser");
        assertEquals("testUser", foundUser.getUsername());
    }
}

2.4 @WebMvcTest

@WebMvcTest 用於測試 Web 層(通常是 Controller),不載入 Service 和 Repository 層。適合測試請求到 Controller 的對映和驗證等。

示例:

@WebMvcTest(SomeController.class)
public class SomeControllerTests {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private SomeService someService;

    @Test
    public void testGetMethod() throws Exception {
        when(someService.getSomeData()).thenReturn("mock data");

        mockMvc.perform(get("/some-endpoint"))
               .andExpect(status().isOk())
               .andExpect(content().string("mock data"));
    }
}

2.5 @JsonTest

@JsonTest 用於測試 JSON 序列化和反序列化過程。它會載入 JSON 相關的 Bean,如 ObjectMapper

示例:

@JsonTest
public class JsonSerializationTests {

    @Autowired
    private JacksonTester<MyObject> json;

    @Test
    public void testSerialize() throws IOException {
        MyObject myObject = new MyObject("value");
        assertThat(this.json.write(myObject)).isEqualToJson("expected.json");
    }
}

3. 測試中的 MockMVC 用法

MockMvc 是 Spring 提供的一個測試工具,用於模擬 HTTP 請求並驗證響應。它可以搭配 @WebMvcTest 註解使用,也可以在 @SpringBootTest 環境下手動建立。

示例:

@SpringBootTest
@AutoConfigureMockMvc
public class WebApplicationTests {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testEndpoint() throws Exception {
        mockMvc.perform(get("/api/hello"))
               .andExpect(status().isOk())
               .andExpect(content().string("Hello World"));
    }
}

4. 測試資料的準備和清理

在測試中,通常需要一些初始化資料,Spring Boot 提供了 @Sql 註解,可以在測試開始時執行 SQL 指令碼,此外 @Transactional 註解可以在每次測試結束後自動回滾資料。

示例:

@SpringBootTest
@Transactional
@Sql(scripts = "/test-data.sql")
public class TransactionalTests {

    @Autowired
    private UserRepository userRepository;

    @Test
    public void testFindUser() {
        User user = userRepository.findByUsername("testUser");
        assertNotNull(user);
    }
}

5. 測試配置的分離

如果需要為不同環境提供不同的測試配置,可以使用 @ActiveProfiles 註解,指定要載入的配置檔案。

示例:

@SpringBootTest
@ActiveProfiles("test")
public class ProfileBasedTests {

    @Autowired
    private SomeService someService;

    @Test
    public void testServiceMethod() {
        assertNotNull(someService);
    }
}

6. 測試 RestTemplate

如果你的應用依賴 RestTemplate 進行外部 API 呼叫,可以使用 MockRestServiceServer 模擬外部服務。

示例:

@SpringBootTest
public class RestTemplateTests {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RestTemplateBuilder restTemplateBuilder;

    private MockRestServiceServer mockServer;

    @BeforeEach
    public void setup() {
        this.mockServer = MockRestServiceServer.createServer(restTemplate);
    }

    @Test
    public void testRestTemplate() {
        this.mockServer.expect(requestTo("/some-api"))
                .andRespond(withSuccess("response", MediaType.APPLICATION_JSON));

        String response = restTemplate.getForObject("/some-api", String.class);
        assertEquals("response", response);
    }
}

7. 總結

以上介紹了 Spring Boot Test 的主要功能和用法,通常可以從以下幾步開始:

  1. 單元測試:使用 @MockBeanMockito 等工具模擬依賴。
  2. 整合測試:使用 @SpringBootTest 執行完整的應用上下文。
  3. Web 層測試:使用 @WebMvcTestMockMvc
  4. 資料庫測試:使用 @DataJpaTest 測試 JPA 層。
  5. 配置分離:使用 @ActiveProfiles 指定不同環境配置。

掌握這些工具和註解後,可以覆蓋 Spring Boot 應用的絕大部分功能測試需求。

相關文章