單元測試
單元測試注意事項(xiàng)
- 測試方法必須用@Test修飾
- 測試方法必須使用public void修飾,不能帶參數(shù)
- 一般使用單元測試會新建一個(gè)test目錄存放測試代碼蛉艾,在生產(chǎn)部署時(shí)只要將test代碼目錄刪除即可
- 測試代碼的包應(yīng)該和被測試代碼的包結(jié)構(gòu)一致
- 測試單元中的每個(gè)方法必須可以獨(dú)立測試杈曲,方法間不能有任何依賴
- 測試類一般用Test作為類名后綴
- 測試放一般使用test作為方法名前綴
常用注解
- @Test:將一個(gè)普通方法修飾稱一個(gè)測試方法
- @Test(excepted==xx.class) 忽略某異常類
- @Test(timeout=毫秒數(shù)) 測試方法執(zhí)行時(shí)間是否符合預(yù)期
- @BeforeClass:會在所有方法執(zhí)行前執(zhí)行
- @Afterclass:會在所有方法執(zhí)行后執(zhí)行
- @Before:在每一個(gè)測試方法被運(yùn)行前執(zhí)行一次
- @After:在每一個(gè)測試方法運(yùn)行后執(zhí)行一次
- @Ignore:修飾的方法會被測試運(yùn)行器忽略
- @RunWith:更改測試運(yùn)行器
- @RunWith(SpringRunner.class)
Spring Boot 單元測試
- Spring Boot 提供了兩個(gè)包來支持單元測試:
- spring-boot-test:包含測試的核心
- spring-boot-test-autoconfigure:用來支持測試的自動配置
配置相關(guān)注解
@SpringBootTest
- 它能夠測試 SpringApplication谷炸,因?yàn)?SpringBoot 程序入口是SpringApplication遥赚,基本所有配置都會通過入口類去加載疏咐,也可以通過 classes 屬性設(shè)置應(yīng)用程序入口類,webEnvironment 可以設(shè)置 web 測試環(huán)境脐供,可選屬性有:
- MOCK:提供一個(gè)模擬的Servlet環(huán)境浑塞,內(nèi)置的Servlet容器沒有啟動,配合@AutoConfigureMockMvc使用
- RANDOM_PORT:提供真實(shí)的Servlet環(huán)境政己,啟動內(nèi)置容器酌壕,隨即端口
- DEFINED_PORT:配置真實(shí)Servlet環(huán)境,使用默認(rèn)端口
- NONE:提供跟Mock一樣不真實(shí)的Servlet環(huán)境
@LocalServerPort
- 注解在屬性上歇由,注入端口號
@ActiveProfiles(profiles = "test")
- 指定多環(huán)境測試時(shí)的環(huán)境配置
@Slf4j
- 如果不想每次都寫下面代碼可以用注解@Slf4j
private final Logger logger = LoggerFactory.getLogger(XXX.class);
@AutoConfigureMockMvc
- 配合 @SpringBootTest 注入一個(gè) MockMvc 實(shí)例
@WebAppConfiguration
- 聲明一個(gè)用于測試的 ApplicationContext 來模擬 ServletContext
測試?yán)?/h2>
測試 REST 接口
- 測試 REST 接口可以配合 TestRestTemplate
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class卵牍,webEnvironment = WebEnvironment.RANDOM_PORT)
public class RandomPortExampleTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void exampleTest() {
String body = this.restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World");
}
}
測試 Spring MVC
- 測試 SpringMVC Controller 可以使用 @WebMvcTEst,它會自動配置 MockMvc沦泌,Mock MVC 提供了一種方法來測試 MVC Controller糊昙,而不用啟動完整的 HTTP Server
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@AutoConfigureMockMvc
public class SessionControllerTest {
@Autowired
private MockMvc mvc;
private ObjectMapper objectMapper = new ObjectMapper();
@Test
public void testLogin() throws Exception {
LoginDTO loginDTO = new LoginDTO();
loginDTO.setUsername("linyuan");
loginDTO.setPassword("123456");
byte[] body = objectMapper.writeValueAsBytes(loginDTO);
String resp = this.mvc.perform(
post("/session") //請求的URL
.content(body) //請求的數(shù)據(jù)
.param("請求的參數(shù)名","參數(shù)值") //請求的參數(shù)
.contentType(MediaType.APPLICATION_JSON) //請求數(shù)據(jù)的格式
.accept(MediaType.APPLICATION_JSON) //接收返回?cái)?shù)據(jù)的格式
).andExpect(status().isOk()) //驗(yàn)證執(zhí)行結(jié)果狀態(tài)碼
.andDo(print()) //請求結(jié)果處理,輸出請求結(jié)果
.andReturn().getResponse().getContentAsString(); //最后返回的結(jié)果谢谦,將數(shù)據(jù)轉(zhuǎn)換為字符串
System.out.println(resp);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class卵牍,webEnvironment = WebEnvironment.RANDOM_PORT)
public class RandomPortExampleTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void exampleTest() {
String body = this.restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World");
}
}
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@AutoConfigureMockMvc
public class SessionControllerTest {
@Autowired
private MockMvc mvc;
private ObjectMapper objectMapper = new ObjectMapper();
@Test
public void testLogin() throws Exception {
LoginDTO loginDTO = new LoginDTO();
loginDTO.setUsername("linyuan");
loginDTO.setPassword("123456");
byte[] body = objectMapper.writeValueAsBytes(loginDTO);
String resp = this.mvc.perform(
post("/session") //請求的URL
.content(body) //請求的數(shù)據(jù)
.param("請求的參數(shù)名","參數(shù)值") //請求的參數(shù)
.contentType(MediaType.APPLICATION_JSON) //請求數(shù)據(jù)的格式
.accept(MediaType.APPLICATION_JSON) //接收返回?cái)?shù)據(jù)的格式
).andExpect(status().isOk()) //驗(yàn)證執(zhí)行結(jié)果狀態(tài)碼
.andDo(print()) //請求結(jié)果處理,輸出請求結(jié)果
.andReturn().getResponse().getContentAsString(); //最后返回的結(jié)果谢谦,將數(shù)據(jù)轉(zhuǎn)換為字符串
System.out.println(resp);
}
}
----- 持續(xù)更新中 -----