2016-09-13 41 views
0

我一起工作:Spring MVC的測試與Hamcrest:如何直接比較一個XML的節點對一個Java對象

  • Spring MVC的測試
  • Hamcrest

對於從集合這樣一個項目如:

<collection> 
    <item xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="persona"> 
     <id>087</id> 
     <nombre>Leonardo</nombre> 
     <apellido>Jordan</apellido> 
     <fecha>1981-07-05</fecha> 
    </item> 
    .... 

以下工作:

.andExpect(xpath("collection/item[1]").exists()) 
.andExpect(xpath("collection/item[1]/*").nodeCount(is(4))) 
.andExpect(xpath("collection/item[1]/id").exists()) 
.andExpect(xpath("collection/item[1]/id").string(is("087"))) 
.andExpect(xpath("collection/item[1]/id").string(is(personasArray[0].getId()))) 
.andExpect(xpath("collection/item[1]/nombre").exists()) 
.andExpect(xpath("collection/item[1]/nombre").string(is("Leonardo"))) 
.andExpect(xpath("collection/item[1]/nombre").string(is(personasArray[0].getNombre()))) 
.andExpect(xpath("collection/item[1]/apellido").exists()) 
.andExpect(xpath("collection/item[1]/apellido").string(is("Jordan"))) 
.andExpect(xpath("collection/item[1]/apellido").string(is(personasArray[0].getApellido()))) 

我想知道是否可以做一個對象而不是每個領域的直接比較,考慮一個具有15到45個字段的實體。

我需要的是這樣的:

.andExpect(xpath("collection/item[1]/*").how(is(personasArray[0]))) 

how部分,它所代表的是使用正確的方法。 path的String內容的同樣考慮因素。

回答

1

有可能做這樣的斷言。但是,您需要爲此編寫自定義ResultMatcher。我認爲將XML(節點)轉換爲Java對象並不是一個好主意,只是爲了在單元測試中做一個簡單的比較。 如果沒有正確實施,您可能會遇到XML名稱空間分辨率問題或Java合同問題。相反,您應該使用庫,讓您專注於單元測試,而不是技術或編程語言的細節。

我建議您在測試中使用XMLUnitXMLUnit是一個用於XML比較的Java庫。

下面的示例描述了將XML文檔與XMLUnit進行比較以及自定義ResultMatcher是多麼容易。

import org.hamcrest.Matcher; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; 
import org.springframework.test.context.junit4.SpringRunner; 
import org.springframework.test.web.servlet.MockMvc; 
import org.springframework.test.web.servlet.ResultMatcher; 
import org.springframework.test.web.servlet.result.MockMvcResultMatchers; 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RestController; 
import org.xmlunit.builder.Input; 

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 
import static org.xmlunit.matchers.CompareMatcher.isSimilarTo; 

@RunWith(SpringRunner.class) 
@WebMvcTest(XmlUnitDemoTests.XmlUnitDemo.class) 
public class XmlUnitDemoTests { 

    static final String XML_CONTENT = "<node1><node2 id=\"1\">text</node2></node1>"; 

    @Autowired 
    MockMvc mockMvc; 

    @Test 
    public void xmlUnit() throws Exception { 
     mockMvc.perform(get("/xml")) 
      .andExpect(xml(XML_CONTENT)); 
    } 

    static ResultMatcher xml(String bodyValue) { 
     return MockMvcResultMatchers.content().source(equalXml(bodyValue)); 
    } 

    static Matcher equalXml(String value) { 
     return isSimilarTo(Input.fromString(value).build()); 
    } 

    @SpringBootApplication 
    @RestController 
    static class XmlUnitDemo { 

     @RequestMapping(value = "xml", produces = "text/xml") 
     String xml() { 
      return XML_CONTENT; 
     } 
    } 

} 

當然,您可以在進行比較之前從classpath中加載大的XML文件或選擇帶有XPatch的節點。請查看XMLUnit文檔以獲取更多信息。

+0

感謝您的文章,我會檢查您的寶貴建議。現在關於'我認爲將XML(節點)轉換爲Java對象並不是一個好主意,只是爲了在單元測試中做一個簡單的比較'我會同意。我理解你的觀點,當然是有效的,但我必須假設遠程客戶端具有OXM技術。我和傑克遜一起爲'XML'和'JSON'工作。 –

+0

你有更好的內在你的項目設置,你是唯一一個可以做出正確決定的人。我只想分享我的意見和經驗與你。 –

+0

我不是說你的意見是錯誤的。我同意,但我的觀點是'快速'@'測試'編纂。想象一下,如果你添加或重構域類。我會測試你的建議。這很有價值。一切都好。再次感謝您的帖子。 –

相關問題