com.github.tomakehurst.wiremock.verification.Diff Maven / Gradle / Ivy
package com.github.tomakehurst.wiremock.verification;
import com.github.tomakehurst.wiremock.common.Json;
import com.github.tomakehurst.wiremock.common.Xml;
import com.github.tomakehurst.wiremock.http.Cookie;
import com.github.tomakehurst.wiremock.http.HttpHeader;
import com.github.tomakehurst.wiremock.http.MultiValue;
import com.github.tomakehurst.wiremock.http.Request;
import com.github.tomakehurst.wiremock.http.RequestMethod;
import com.github.tomakehurst.wiremock.matching.EqualToJsonPattern;
import com.github.tomakehurst.wiremock.matching.EqualToPattern;
import com.github.tomakehurst.wiremock.matching.EqualToXmlPattern;
import com.github.tomakehurst.wiremock.matching.MultiValuePattern;
import com.github.tomakehurst.wiremock.matching.RequestPattern;
import com.github.tomakehurst.wiremock.matching.StringValuePattern;
import com.github.tomakehurst.wiremock.matching.ValueMatcher;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.collect.FluentIterable.from;
public class Diff {
private final RequestPattern requestPattern;
private final Request request;
public Diff(RequestPattern expected, Request actual) {
this.requestPattern = expected;
this.request = actual;
}
@Override
public String toString() {
ImmutableList.Builder> builder = ImmutableList.builder();
Section methodSection = new Section<>(requestPattern.getMethod(), request.getMethod(), requestPattern.getMethod().getName());
builder.add(methodSection);
Section urlSection = new Section<>(requestPattern.getUrlMatcher(),
request.getUrl(),
requestPattern.getUrlMatcher().getExpected());
builder.add(urlSection);
if (methodSection.shouldBeIncluded() || urlSection.shouldBeIncluded()) {
builder.add(SPACER);
}
boolean anyHeaderSections = false;
Map headerPatterns = requestPattern.combineBasicAuthAndOtherHeaders();
if (headerPatterns != null && !headerPatterns.isEmpty()) {
for (String key : headerPatterns.keySet()) {
HttpHeader header = request.header(key);
MultiValuePattern headerPattern = headerPatterns.get(header.key());
String printedPatternValue = header.key() + ": " + headerPattern.getExpected();
Section section = new Section<>(headerPattern, header, printedPatternValue);
if (section.shouldBeIncluded()) {
anyHeaderSections = true;
}
builder.add(section);
}
}
if (anyHeaderSections) {
builder.add(SPACER);
}
boolean anyCookieSections = false;
if (requestPattern.getCookies() != null) {
Map cookies = firstNonNull(request.getCookies(), Collections.emptyMap());
for (Map.Entry entry: requestPattern.getCookies().entrySet()) {
String key = entry.getKey();
StringValuePattern pattern = entry.getValue();
Cookie cookie = firstNonNull(cookies.get(key), Cookie.absent());
Section section = new Section<>(
pattern,
cookie.isPresent() ? "Cookie: " + key + "=" + cookie.getValue() : "",
"Cookie: " + key + "=" + pattern.getValue()
);
builder.add(section);
anyCookieSections = true;
}
}
if (anyCookieSections) {
builder.add(SPACER);
}
List bodyPatterns = requestPattern.getBodyPatterns();
if (bodyPatterns != null && !bodyPatterns.isEmpty()) {
for (StringValuePattern pattern: bodyPatterns) {
String body = formatIfJsonOrXml(pattern);
builder.add(new Section<>(pattern, body, pattern.getExpected()));
}
}
List> sections = builder.build();
String expected = Joiner.on("\n")
.join(from(sections).transform(EXPECTED));
String actual = Joiner.on("\n")
.join(from(sections).transform(ACTUAL));
return sections.isEmpty() ? "" : junitStyleDiffMessage(expected, actual);
}
private String formatIfJsonOrXml(StringValuePattern pattern) {
return pattern.getClass().equals(EqualToJsonPattern.class) ?
Json.prettyPrint(request.getBodyAsString()) :
pattern.getClass().equals(EqualToXmlPattern.class) ?
Xml.prettyPrint(request.getBodyAsString()) :
request.getBodyAsString();
}
public static String junitStyleDiffMessage(Object expected, Object actual) {
return String.format(" expected:<\n%s> but was:<\n%s>", expected, actual);
}
final Section SPACER = new Section(new EqualToPattern(""), "", "");
private class Section {
private final ValueMatcher pattern;
private final V value;
private final String printedPatternValue;
public Section(ValueMatcher pattern, V value, String printedPatternValue) {
this.pattern = pattern;
this.value = value;
this.printedPatternValue = printedPatternValue;
}
public Object getExpected() {
return shouldBeIncluded() ?
printedPatternValue :
value;
}
public Object getActual() {
return value;
}
private boolean shouldBeIncluded() {
return !pattern.match(value).isExactMatch();
}
}
private static Function, Object> EXPECTED = new Function, Object>() {
@Override
public Object apply(Section input) {
return input.getExpected();
}
};
private static Function, Object> ACTUAL = new Function, Object>() {
@Override
public Object apply(Section input) {
return input.getActual();
}
};
}