libary 有兩個
spring-boot-test: 測試核心功能
spring-boot-test-autoconfigure: 測試的自動設定
spring-boot-starter-test 是集合
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
測試還包含其他 library
JUnit 5
AssertJ
Hamcrest
Mockito
JSONassert
JsonPath
spring 提供一個 @SpringBootTest
annotation,裡面有一個 webEnvironment 環境變數,支援以下設定
MOCK (default)
載入一個 WebApplicationContext 並提供 Mock Web Environment。不會啟動內嵌的 web server,並可以結合
@AutoConfigureMockMvcor
@AutoConfigureWebTestClient
進行 MOCK 測試RANDOM_PORT
載入一個 WebApplicationContext,提供一個真實的 web environment,隨機 port
DEFINED_PORT
載入一個 WebApplicationContext,提供一個真實的 web environment,指定 port,預設 8080
NONE
載入一個 WebApplicationContext,不提供 web environment
Spring MVC 測試
MvcTests.java
package com.test.test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import java.util.HashMap;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MvcTests {
@Test
public void getUserTest(@Autowired TestRestTemplate testRestTemplate) {
Map<String, String> multiValueMap = new HashMap<>();
multiValueMap.put("username", "test1");
Result result = testRestTemplate.getForObject("/user/get?username={username}",
Result.class, multiValueMap);
assertThat(result.getCode()).isEqualTo(0);
assertThat(result.getMsg()).isEqualTo("ok");
}
}
呼叫 /user/test,檢查回傳的資料是否正確
從 log 可發現 tomcat 運作在另一個 port
Tomcat started on port 53594 (http) with context path '/'
MOCK 測試
package com.test.test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest
@AutoConfigureMockMvc
class MockMvcTests {
@Test
public void getUserTest(@Autowired MockMvc mvc) throws Exception {
mvc.perform(MockMvcRequestBuilders.get("/user/get?username={username}", "test"))
.andExpect(status().isOk())
.andExpect(content().string("{\"code\":0,\"msg\":\"ok\",\"data\":\"test\"}"));
}
}
在class 上面增加 @AutoConfigureMockMvc
,然後在 method 上加上 @Autowired MockMvc mvc
就可進行 MOCK 測試。
從 log 發現並沒有真的啟動一個 web server
MOCK 元件測試
package com.test.test;
import com.test.test.service.UserService;
import org.junit.jupiter.api.Test;
import org.mockito.BDDMockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
class MockBeanTests {
// @Autowired
// private UserService userService;
@MockitoBean
private UserService userService;
@Test
public void countAllUsers() {
BDDMockito.given(this.userService.countAllUsers()).willReturn(88);
assertThat(this.userService.countAllUsers()).isEqualTo(88);
}
}
@MockitoBean
代表該變數是被 Mock 覆蓋
這邊透過 BDDMockito 模擬 countAllUsers 回傳結果
JSON 測試
spring 提供各種技術元件的單元測試
想要測試 JSON,可使用 JsonTestersAutoConfiguration,只需要在測試類別加上 @JsonTest
先新增一個檔案 test/resources/jack.json
{"id":10001, "name":"Jack", "birthday": "2000-10-08 21:00:00"}
User POJO
package com.test.test;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
public class User {
private long id;
private String name;
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime birthday;
}
JsonTests.java
package com.test.test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.json.JsonTest;
import org.springframework.boot.test.json.JacksonTester;
import java.time.LocalDateTime;
import static org.assertj.core.api.Assertions.assertThat;
@JsonTest
class JsonTests {
@Autowired
private JacksonTester<User> json;
@Test
void serialize() throws Exception {
User user = new User(10001L, "Jack",
LocalDateTime.of(2000, 10, 8, 21, 0, 0));
assertThat(this.json.write(user)).isEqualToJson("/jack.json");
assertThat(this.json.write(user)).hasJsonPathStringValue("@.name");
assertThat(this.json.write(user)).
extractingJsonPathStringValue("@.name").isEqualTo("Jack");
}
@Test
void deserialize() throws Exception {
String content = "{\"id\":10002, \"name\":\"Petty\", \"birthday\": \"2025-01-01 01:01:00\"}";
assertThat(this.json.parse(content))
.isEqualTo(new User(10002L, "Petty",
LocalDateTime.of(2025, 1, 1, 1, 1, 0)));
assertThat(this.json.parseObject(content).getName()).isEqualTo("Petty");
}
}
沒有留言:
張貼留言