2016-12-02 93 views
3

在Spring REST控制器中創建資源後,我將返回它在標題中的位置,如下所示。Spring REST控制器的單元測試'位置'標題

@RequestMapping(..., method = RequestMethod.POST) 
public ResponseEntity<Void> createResource(..., UriComponentsBuilder ucb) { 

    ... 

    URI locationUri = ucb.path("/the/resources/") 
     .path(someId) 
     .build() 
     .toUri(); 

    return ResponseEntity.created(locationUri).build(); 
} 

在單元測試中,我正在檢查它的位置,如下所示。

@Test 
public void testCreateResource(...) { 
    ... 
    MockHttpServletRequestBuilder request = post("...") 
     .content(...) 
     .contentType(MediaType.APPLICATION_JSON) 
     .accept(MediaType.APPLICATION_JSON); 

    request.session(sessionMocked); 

    mvc.perform(request) 
     .andExpect(status().isCreated()) 
     .andExpect(header().string("Location", "/the/resources" + id); 
} 

此結果案例失敗並顯示以下消息。

java.lang.AssertionError: Response header Location expected:</the/resources/123456> but was:<http://localhost/the/resources/123456> 

好像我必須爲期望的位置標題提供上下文前綴http://localhost

  • 硬編碼上下文安全嗎?如果是這樣,爲什麼?
  • 如果不是,那麼正確地爲測試用例生成正確的方法是什麼?

回答

1

如果您不需要在響應的Location標頭中有一個完整的URI(即沒有要求,設計約束等):考慮切換到使用相對URI(從HTTP標準角度來看這是有效的 - 請參閱[1]:https://tools.ietf.org/html/rfc7231)相對URI是現代瀏覽器和庫支持的建議標準。這將允許您測試端點的行爲,並使其從長遠來看不那麼脆弱。

如果您需要斷言的完整路徑,因爲你正在使用MockMvc,你可以在測試請求設置URI到你想要什麼:

@Autowired 
private WebApplicationContext webApplicationContext; 

@Test 
public void testCreateResource() { 
    MockMvc mvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); 
    mvc.perform(MockMvcRequestBuilders.get(new URI("http://testserver/the/resources"))); 

這將使注入建設者產生「http://testserver 「當構建被調用時。請注意,未來的框架更改可能會導致您頭痛,如果他們刪除此測試行爲。

2

我在猜測,因爲您使用UriComponentsBuilder來建立您的URI它設置您的位置標題中的主機名。如果你使用的只是new URI("/the/resources")之類的東西,你的測試已經過去了。

在你的情況,我會使用redirectedUrlPattern匹配重定向URL:

.andExpect(redirectedUrlPattern("http://*/the/resources"))

這將匹配任何主機名,所以你不必硬編碼本地主機。詳細瞭解您可以與AntPathMatcherhere一起使用的不同模式。

+0

您的解決方案測試重定向行爲。 OP想要測試位置標頭。 我必須承認,直到今天我都不知道「redirectedUrlPattern」 –