Testing with Hoverfly and Java Part 5: XML and Xpath matchers
Previously we worked with some of the existing Hoverfly matchers like the regex, glob and exact.
Each one serves its purpose but we might want some rules that assist us with the format of the data exchanged through our requests.
On this blog we will focus on the matchers for xml.
The default xml matcher will compare the xml submitted with the xml expected. This means that the submitted xml shall be validated node by node value by value. New lines or any extra spaces as long as they don’t change the content that the xml carries will not prevent the request from being a success.
Let’s put our initial configuration that will make the xml match.
public static final String SUCCESS_RESPONSE = "<response>" + "<result>success</result>" + "</response>"; private Hoverfly hoverfly; @BeforeEach void setUp() { var simulation = SimulationSource.dsl(service("http://localhost:8085") .post("/xml") .body(RequestFieldMatcher.newXmlMatcher("<document type=\"xml\">" + "xml-request" + "</document>")) .willReturn(success(SUCCESS_RESPONSE, "application/xml"))); var localConfig = HoverflyConfig.localConfigs().disableTlsVerification().asWebServer().proxyPort(8085); hoverfly = new Hoverfly(localConfig, SIMULATE); hoverfly.start(); hoverfly.simulate(simulation); } @AfterEach void tearDown() { hoverfly.close(); }
So in our first example we will try to match the xml of our request with the xml expected.
@Test void testXmlExactMatch() { var client = HttpClient.newHttpClient(); var exactRequest = HttpRequest.newBuilder() .uri(URI.create("http://localhost:8085/xml")) .POST(HttpRequest.BodyPublishers.ofString(" <document type=\"xml\">\n\n" + "xml-request" + "</document>\t")) .build(); var exactResponse = client.sendAsync(exactRequest, HttpResponse.BodyHandlers.ofString()) .thenApply(HttpResponse::body) .join(); Assertions.assertEquals(SUCCESS_RESPONSE, exactResponse); }
As you see regardless of the new lines and the tabs, our request will be successful since the xml data do match.
Now let’s try to add a node to the xml.
@Test void testXmlNoMatch() { var client = HttpClient.newHttpClient(); var exactRequest = HttpRequest.newBuilder() .uri(URI.create("http://localhost:8085/xml")) .POST(HttpRequest.BodyPublishers.ofString(" <document type=\"xml\">\n\n" + "xml-request" + "</document>\t<empty-node>ok</empty-node>")) .build(); var exactResponse = client.sendAsync(exactRequest, HttpResponse.BodyHandlers.ofString()) .join(); Assertions.assertEquals(502, exactResponse.statusCode()); }
The xml does not match thus it will fail.
Let’s focus to another problem. Since the data exchanged are dynamic, chances are that exact matches might not be possible. Also you might not need to focus on all the information submitted but just a specific section of the information exchanged. Therefore an XPath matcher becomes handy.
Will enhance the initial setup with an XPath rule.
@BeforeEach void setUp() { var simulation = SimulationSource.dsl(service("http://localhost:8085") .post("/xml") .body(RequestFieldMatcher.newXmlMatcher("<document type=\"xml\">" + "xml-request" + "</document>")) .willReturn(success(SUCCESS_RESPONSE, "application/xml")) .post("/xpath") .body(RequestFieldMatcher.newXpathMatcher("/document/payment[amount=1]")) .willReturn(success(SUCCESS_RESPONSE, "application/xml")) ); var localConfig = HoverflyConfig.localConfigs().disableTlsVerification().asWebServer().proxyPort(8085); hoverfly = new Hoverfly(localConfig, SIMULATE); hoverfly.start(); hoverfly.simulate(simulation); }
If there is a document node with a payment node and the value on the amount node is 1 there will be a match
Let’s go for a positive scenario
@Test void testXpathMatch() { var client = HttpClient.newHttpClient(); var exactRequest = HttpRequest.newBuilder() .uri(URI.create("http://localhost:8085/xpath")) .POST(HttpRequest.BodyPublishers.ofString(" <document type=\"xml\">\n\n" + "<payment><amount>142</amount></payment>" + "<payment><amount>1</amount><currency>GBP</currency></payment>" + "<payment>invalid</payment>" + "</document>\t")) .build(); var exactResponse = client.sendAsync(exactRequest, HttpResponse.BodyHandlers.ofString()) .thenApply(HttpResponse::body) .join(); Assertions.assertEquals(SUCCESS_RESPONSE, exactResponse); }
As expected we got a match.
Let’s go for a negative scenario.
@Test void testXpathNoMatch() { var client = HttpClient.newHttpClient(); var exactRequest = HttpRequest.newBuilder() .uri(URI.create("http://localhost:8085/xpath")) .POST(HttpRequest.BodyPublishers.ofString(" <document type=\"xml\">\n\n" + "<payment><amount>142</amount></payment>" + "<payment><amount>no-match</amount><currency>GBP</currency></payment>" + "<payment>invalid</payment>" + "</document>\t")) .build(); var exactResponse = client.sendAsync(exactRequest, HttpResponse.BodyHandlers.ofString()) .join(); Assertions.assertEquals(502, exactResponse.statusCode()); }
That’s it we did use the xml and xpath matchers for the xml based data. The next blog shall focus on the JSON based matchers.
Published on Java Code Geeks with permission by Emmanouil Gkatziouras, partner at our JCG program. See the original article here: Testing with Hoverfly and Java Part 5: XML and Xpath matchers Opinions expressed by Java Code Geeks contributors are their own. |