參考文章:Spring MVC全註解配置 - 無web.xml
單元測試的目的,簡單來說就是在我們增加或者改動一些代碼以後對所有邏輯的一個檢測,尤其是在我們後期修改後(不論是增加新功能,修改bug),都可以做到重新測試的工作。以減少我們在發佈的時候出現更過甚至是出現之前解決了的問題再次重現。
Spring MVC的測試往往看似比較複雜。其實他的不同在於,他需要一個ServletContext來模擬我們的請求和響應。但是Spring也針對Spring MVC 提供了請求和響應的模擬測試接口,以方便我們的單元測試覆蓋面不只是service,dao層。
我們會結合上一篇文章的配置進行junit的測試。上一篇文章中我們使用純java代碼來配置spring mvc,因此在我們書寫junit測試的時候,有三點需要注意,這個和平時的junit測試有點不同
在測試類上的@ContextConfiguration註解需要指定spring的配置文件,由於我們使用的是java配置,所以這裏傳遞我們的配置類,記住是spring的配置類,而不是web的配置類(注:web的配置我們是通過模擬的)。
因爲controller,component等都是使用註解來,所以我們的@ContextConfiguration使用的是直接來加載的。因此在他的屬性中,配置一個loader。同時由於是web的,所以使用AnnotationConfigWebContextLoader。
由於需要模擬ServletContext,因此我們需要給我們的測試類加上@WebAppConfiguration。
代碼如下:
@RunWith(Parameterized.class) @ContextConfiguration(classes = { WebMVCConfiguration.class }, loader = AnnotationConfigWebContextLoader.class) @WebAppConfiguration public class ControllerTest
我的目的是使用參數化來測試controller,所以使用的是@RunWith是參數化的runner。由於junit的runner只能有一個,所以我們這裏用另外的方式來讓spring的功能也集成進來。
下面一步就是編寫我們的測試controller,代碼如下:
@Controller public class TestController { @RequestMapping(value = "/test", method = RequestMethod.GET) public @ResponseBody String test(String name) { return name; } }
在我們的測試類中,我們就正對此Controller的方法進行一個參數的構造。
Junit中參數構造這裏就不多講,@Parameters來標記數據集合,私有屬性和構造函數來對應我們的傳入參數與預期結果。因此在ControllerTest中我們這樣構造數據:
// parameters private String name; private String result; public ControllerTest(String name, String result) { this.name = name; this.result = result; } @Parameters public static Collection<String[]> data() { return Arrays.asList(new String[][] { { "Troy", "Troy" }, { "Young", "Young" } }); }
在模擬http request response之前我們需要去模擬一個request和response的環境,同時也要讓我們的spring的功能融入進來,這樣才能方便我們使用spring的DI等功能。因此這兩個都在我們test之前進行配置:
private TestContextManager testContextManager; private MockMvc mockMvc; @Autowired private WebApplicationContext wac; @Before public void setUp() throws Exception { testContextManager = new TestContextManager(getClass()); testContextManager.prepareTestInstance(this); mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); }
此時我們已經具備了環境、參數,接下里就進行真正的測試代碼的編寫:
@Test public void test() throws Exception { MvcResult rs = mockMvc.perform( MockMvcRequestBuilders.get("/test?name=" + name)).andReturn(); assertEquals("name is not correct", result, new String(rs.getResponse() .getContentAsByteArray())); }
能夠很好的運行起來,已經達到我們預期的效果。以後的擴展就只用在data裏面去進行擴展配置參數,然後每一次build的時候我們都可以發現我們的build存在bug麼。
很多具體的類使用請自行查閱一下。本文只是講解簡單的操作。