I am testing a controller using MockMvc
. This is what the response looks like:
MockHttpServletResponse:
Status = 200
Error message = null
Headers = {Content-Type=[text/xml]}
Content type = text/xml
Body = <?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:diagnosisCode xmlns:ns2="http://schemas.mycompany.co.za/health" effectiveStartDate="2014-03-05T00:00:00+02:00" effectiveEndDate="2014-03-05T23:59:59.999+02:00" diagnosisId="1"><diagnosisCodeId><codingSchemaCode>irrelevant schema</codingSchemaCode><diagnosisCode>irrelevant code</diagnosisCode></diagnosisCodeId></ns2:diagnosisCode>
Forwarded URL = null
Redirected URL = null
Cookies = []
Pretty-printed version of the Body
line:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:diagnosisCode xmlns:ns2="http://schemas.mycompany.co.za/health" effectiveStartDate="2014-03-05T00:00:00+02:00" effectiveEndDate="2014-03-05T23:59:59.999+02:00" diagnosisId="1">
<diagnosisCodeId>
<codingSchemaCode>irrelevant schema</codingSchemaCode>
<diagnosisCode>irrelevant code</diagnosisCode>
</diagnosisCodeId>
</ns2:diagnosisCode>
The call on MockMvc
looks like
mockMvc.perform(
get("/diagnostic/diagnosisCodes/{schema}/{code}", IRRELEVANT_SCHEMA, IRRELEVANT_CODE).accept(MediaType.TEXT_XML))
.andDo(print())
.andExpect(content().contentType(MediaType.TEXT_XML))
.andExpect(status().isOk())
.andExpect(xpath("diagnosisCodeId/diagnosisCode").string(IRRELEVANT_CODE))
.andExpect(xpath("diagnosisCodeId/codingSchemaCode").string(IRRELEVANT_SCHEMA));
I am pretty sure I am misunderstanding how I'm supposed to use XPath here, but why is this assertion failing? What should my expectation look like?
java.lang.AssertionError: XPath diagnosisCode expected:<irrelevant code> but was:<>
I'm not totally sure what the XPath context is (or whether it is the document node), but I see two possible problems and guess both apply:
You try to match < diagnosisCodeId/>
elements that are the root element. There are none, but they're children of <diagnosisCode>
. Either include an axis step for the root node (probably better way) or use the descendant-or-self
axis step //
in front of the query.
/diagnosisCode/diagnosisCodeId/diagnosisCode
//diagnosisCodeId/diagnosisCode
The document uses namespaces (for the root element). In addition to the root element problem described above, either register that namespace (better solution, but I don't know how to do this in spring MVC) or ignore it using following workaround:
/*[local-name() = 'diagnosisCode']/diagnosisCodeId/diagnosisCode
Which first matches all child nodes, but then limits to the ones having the apropriate element name (ignoring namespaces).
By adding XPath 2.0 support (for example by including Saxon as library), you can also use the wildcard namespace matcher:
/*:diagnosisCode/diagnosisCodeId/diagnosisCode
If you register the namespace URI http://schemas.mycompany.co.za/health
as ns2
, the query would look like
/ns2:diagnosisCode/diagnosisCodeId/diagnosisCode