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.
0 comments:
Post a Comment