Spring Mock- MVC menyediakan metode pengujian yang sangat baik untuk Spring Boot REST API. Mock-MVC memungkinkan kita untuk menguji penanganan permintaan Spring-MVC tanpa memulai server sebenarnya.
Saya telah menggunakan tes Mock-MVC pada berbagai proyek dan menurut pengalaman saya seringkali cukup bertele-tele. Ini tidak selalu berarti buruk. Namun, ini sering kali memerlukan penyalinan / penempelan fragmen kode yang serupa ke dalam kelas pengujian. Dalam posting ini, kita akan melihat beberapa cara untuk meningkatkan tes Spring Mock-MVC.
Putuskan apa yang akan diuji dengan Mock-MVC
Pertanyaan pertama yang perlu kami tanyakan adalah apa yang ingin kami uji dengan Mock-MVC. Berikut beberapa contoh kasus uji:
Menguji hanya lapisan web dan meniru semua dependensi pengontrol.
Menguji tingkat web dengan logika domain dan mensimulasikan dependensi pihak ketiga seperti database atau antrian pesan.
Menguji jalur lengkap dari lapisan web ke database dengan mengganti dependensi pihak ketiga dengan alternatif yang disematkan jika memungkinkan (misalnya H2 atau tertanam-Kafka )
Semua skenario ini memiliki pro dan kontra. Namun, menurut saya ada dua aturan sederhana yang harus kita ikuti:
Uji sebanyak mungkin dalam pengujian JUnit standar (tanpa Pegas). Ini sangat meningkatkan kinerja pengujian dan mempermudah penulisan pengujian.
(-), Spring, , . . Spring , .
JUnit . , , Mock-MVC, , , .
Spring Spring .
, @MockMvcTest:
@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
@AutoConfigureMockMvc(secure = false)
@Retention(RetentionPolicy.RUNTIME)
public @interface MockMvcTest {}:
@MockMvcTest
public class MyTest {
...
}, . Spring .
Mock-MVC
Mock-MVC , :
mockMvc.perform(put("/products/42")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content("{\"name\": \"Cool Gadget\", \"description\": \"Looks cool\"}")
.header("Authorization", getBasicAuthHeader("John", "secr3t")))
.andExpect(status().isOk());PUT JSON /products/42.
, - JSON Java. , , , , Java, .
, JSON. , . Java Text JDK 13/14 . - , .
JSON . :
mvc.perform(put("/products/42")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content("""
{
"name": "Cool Gadget",
"description": "Looks cool"
}
""")
.header("Authorization", getBasicAuthHeader("John", "secr3t")))
.andExpect(status().isOk()); .
, -, , JSON , JSON.
:
Product product = new Product("Cool Gadget", "Looks cool");
mvc.perform(put("/products/42")
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(objectToJson(product))
.header("Authorization", getBasicAuthHeader("John", "secr3t")))
.andExpect(status().isOk());product JSON objectToJson(..). . , .
, . JSON REST-API, , PUT. :
public static MockHttpServletRequestBuilder putJson(String uri, Object body) {
try {
String json = new ObjectMapper().writeValueAsString(body);
return put(uri)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON)
.content(json);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}body JSON Jackson ObjectMapper . PUT Accept Content-Type .
:
Product product = new Product("Cool Gadget", "Looks cool");
mvc.perform(putJson("/products/42", product)
.header("Authorization", getBasicAuthHeader("John", "secr3t")))
.andExpect(status().isOk()), . putJson(..) MockHttpServletRequestBuilder. , , (, ).
- , Spring Mock-MVC. putJson(..). PUT , , -.
RequestPostProcessor . , RequestPostProcessor . .
:
public static RequestPostProcessor authentication() {
return request -> {
request.addHeader("Authorization", getBasicAuthHeader("John", "secr3t"));
return request;
};
} authentication() RequestPostProcessor, . RequestPostProcessor with(..):
Product product = new Product("Cool Gadget", "Looks cool");
mvc.perform(putJson("/products/42", product).with(authentication()))
.andExpect(status().isOk()). , , . , putJson(url, data).with(authentication()) .
, .
:
mvc.perform(get("/products/42"))
.andExpect(status().isOk())
.andExpect(header().string("Cache-Control", "no-cache"))
.andExpect(jsonPath("$.name").value("Cool Gadget"))
.andExpect(jsonPath("$.description").value("Looks cool"));HTTP, , Cache-Control no-cache, JSON-Path .
Cache-Control , , , . :
public ResultMatcher noCacheHeader() {
return header().string("Cache-Control", "no-cache");
}, noCacheHeader() andExpect(..):
mvc.perform(get("/products/42"))
.andExpect(status().isOk())
.andExpect(noCacheHeader())
.andExpect(jsonPath("$.name").value("Cool Gadget"))
.andExpect(jsonPath("$.description").value("Looks cool"));.
, product(..), JSON Product:
public static ResultMatcher product(String prefix, Product product) {
return ResultMatcher.matchAll(
jsonPath(prefix + ".name").value(product.getName()),
jsonPath(prefix + ".description").value(product.getDescription())
);
}:
Product product = new Product("Cool Gadget", "Looks cool");
mvc.perform(get("/products/42"))
.andExpect(status().isOk())
.andExpect(noCacheHeader())
.andExpect(product("$", product));, prefix . , , JSON .
, . prefix . :
Product product0 = ..
Product product1 = ..
mvc.perform(get("/products"))
.andExpect(status().isOk())
.andExpect(product("$[0]", product0))
.andExpect(product("$[1]", product1));ResultMatcher . .
Spring Mock-MVC. Mock-MVC, , . ( Spring Mock-MVC).
Spring Mock-MVC. RequestPostProcessor . ResultMatcher .
Anda dapat menemukan kode sampel di GitHub .