Get請求url不超過4000字節
Rest成熟度:level 0:使用http作為傳輸方式,leve 1:引入資源概念,每個資源有對應的url,level 2:使用http方法進行不同操作,使用http狀態碼表示不同結果,level 3:使用超媒體,在資源表達式中包含鏈接信息,一般做到level 2
測試依賴:org.springframework.boot:spring-boot-starter-test
測試類:
package
com.example.security
;
import
org.junit.
Before
;
import
org.junit.runner.
RunWith
;
import
org.springframework.beans.factory.annotation.
Autowired
;
import
org.springframework.boot.test.context.
SpringBootTest
;
import
org.springframework.test.context.junit4.SpringRunner
;
import
org.springframework.test.web.servlet.MockMvc
;
import
org.springframework.test.web.servlet.setup.MockMvcBuilders
;
import
org.springframework.web.context.WebApplicationContext
;
@RunWith
(SpringRunner.
class
)
//使用SpringRunner運行
@SpringBootTest
//表明這是一個測試用例
public class
SecurityApplicationTests {
@Autowired
private
WebApplicationContext
wac
;
//注入web環境,但是並不會啟動Tomcat,所以很快
private
MockMvc
mockMvc
;
//模擬web環境
@Before
//@Before會在每個@Test之前執行,在里面初始化模擬的web環境
public void
setup
() {
mockMvc
= MockMvcBuilders.
webAppContextSetup
(
wac
).build()
;
}
}
Rest請求單元測試舉例(推薦先寫好測試用例,執行,失敗紅色,然后去寫Rest api,過程中不斷執行測試用例,直到測試用例通過):
@Test
public void
queryUsersOK
()
throws
Exception {
mockMvc
.perform(MockMvcRequestBuilders.
get
(
"/users"
)
.contentType(MediaType.
APPLICATION_JSON_UTF8
))
.andExpect(MockMvcResultMatchers.
status
().isOk())
.andExpect(MockMvcResultMatchers.
jsonPath
(
"$.length()"
).value(
2
))
;
}
該測試用例向/users發送get請求,contentType為
application/json;charset=UTF-8
,期望響應狀態碼200,期望響應json字符串數組長度為2。其中jsonPath是用來解析響應的json。
請求格式錯誤會報400。請求的method不匹配會報405。
這里的$代表返回的json文檔,具體可在github搜索jsonPath第一個項目json-path/JsonPath即可,具體使用參考
https://github.com/json-path/JsonPath的Operators和Functions(方法)
注:測試用例中MockMvcRequestBuilders和MockMvcResultMatchers兩個靜態類常用,可以添加到STS的偏好設置,菜單欄Preferences--Java--Editor--Content Assist--Favorites--New Type(直接在Preferences搜索fa即可)
添加到偏好設置以后,自動變成靜態引用,代碼簡化:
//靜態引用
import static
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.
get
;
import static
org.springframework.test.web.servlet.result.MockMvcResultMatchers.
jsonPath
;
import static
org.springframework.test.web.servlet.result.MockMvcResultMatchers.
status
;
//測試用例
@Test
public void
queryByParam
()
throws
Exception {
String result =
mockMvc
.perform(
get
(
"/user"
)
// .param("username", "wangzhongshan")
// .param("password", "kibana")
.contentType(MediaType.
APPLICATION_JSON_UTF8
))
.andExpect(
status
().isOk())
// .andExpect(jsonPath("$.length()").value(1));
.andExpect(
jsonPath
(
"$username"
).value(
"wzs"
))
//斷言返回json對象的屬性的值
.andReturn().getResponse().getContentAsString()
;
//獲取響應的字符串值
}
若要傳遞參數,如圖注釋,添加一到多個.param(String key, String value)即可,生成/user?key=value的查詢,后台可用同名參數或對象的同名屬性接受之,無論后台接受參數/參數對象屬性是什么類型,測試用例的param之value都傳字符串類型。
單元測試執行技巧:在@Test方法上執行run,先執行@Before方法再執行@Test方法,在空白位置執行run,所有@Test都會執行(每個@Test執行之前都會執行@Before),在package上執行run,則包下面所有的測試類的@Test都將執行
常用注解:
@RestController,@RequestMapping及變體(如@GetMapping,其源碼可知是被@RequestMapping注解了並指定了相應的method)
@RequestParam(參數require默認true,必傳,value是name屬性的別名,兩個都是給參數指定名字)
@PathVariable(映射url片段到參數,屬性require默認true,必填,value是name屬性的別名。url聲明
可以使用正則表達式,如@RequestMapping(value = "/user/{id:\\d+}")規范id只能傳整數,否則報400
)
新學注解:
@PageableDefault指定分頁參數默認值(rest api傳輸類建包DTO)
:
org.springframework.data.domain.Pageable(Spring Data提供)
controller可使用該對象接受page,size,sort(排序,值如age,desc)三個分頁參數值,也可以在用@PageableDefault注解Pageable對象,其提供page,size,sort這3個屬性給Pageable提供默認值,代碼:
@RequestMapping
(
"/users"
)
public
List<User>
users
(
@PageableDefault
(
page
=
0
,
size
=
10
,
sort
=
"username, asc"
) Pageable page) {
page.getPageNumber()
;
page.getPageSize()
;
page.getSort()
;
return new
ArrayList<>()
;
}
post請求:參數為json對象,映射到controller方法的參數對象必須要用@RequestBody注解,否則json參數無法映射到參數對象,參數的屬性只能拿到Null。
測試用例(post攜帶content傳參):
import static
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.
post
;
import static
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.
put
;
@Test
public void
createUser
()
throws
Exception {
String content =
"{
\"
username
\"
:
\"
test
\"
,
\"
pasword
\"
:
\"
123456
\"
,
\"
date
\"
:"
+ System.
currentTimeMillis
()+
"}"
;
String result =
mockMvc
.perform(
post
(
"/user"
).contentType(MediaType.
APPLICATION_JSON_UTF8
).content(content)) //put與post的測試用例寫法相同,只是把post改成put,url改成如/usr/1
.andExpect(
status
().isOk()).andExpect(
jsonPath
(
"$.id"
).value(
"1"
))
.andReturn().getResponse().getContentAsString()
;
System.
out
.println(result)
; //時間屬性,向后台傳參是System.currentTImeMillis();,返回的是
2019-08-24T04:06:49.154+0000
}
如果參數對象有Date屬性,可以用yyyy-MM-dd或yyyy-MM-dd HH:mm:ss等時間格式字符串轉換,但是需要轉換且需要適配不同的展示格式,因此直接在json中傳遞時間戳(毫秒值)更方便,入庫存時間戳,前台展示什么樣式由js控制。前台時間戳和后台Date類型能夠自由轉換(經測試,從瀏覽器url傳的date=時間戳轉換失敗)。
刪除單元測試(請求方法使用多了,直接引用*即可):
import static
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*
;
@Test
public void
deleteUser
()
throws
Exception {
mockMvc
.perform(
delete
(
"/user/1"
).contentType(MediaType.
APPLICATION_JSON_UTF8
)).andExpect(
status
().isOk())
;
}