Skip to content

Instantly share code, notes, and snippets.

@leoluz
Created January 13, 2016 21:05
Show Gist options
  • Save leoluz/5e7ad32910911d0b0c4a to your computer and use it in GitHub Desktop.
Save leoluz/5e7ad32910911d0b0c4a to your computer and use it in GitHub Desktop.
A Wiremock listener implementation that records stubs with scenarios allowing you to playback your tests even in complex scenarios that depends on state transitions awareness.
import com.github.tomakehurst.wiremock.common.FileSource
import com.github.tomakehurst.wiremock.common.IdGenerator
import com.github.tomakehurst.wiremock.common.UniqueFilenameGenerator
import com.github.tomakehurst.wiremock.common.VeryShortIdGenerator
import com.github.tomakehurst.wiremock.http.*
import com.github.tomakehurst.wiremock.matching.RequestPattern
import com.github.tomakehurst.wiremock.matching.ValuePattern
import com.github.tomakehurst.wiremock.stubbing.Scenario
import com.github.tomakehurst.wiremock.stubbing.StubMapping
import static com.github.tomakehurst.wiremock.common.Json.write
import static java.util.Arrays.asList
import static org.skyscreamer.jsonassert.JSONCompareMode.LENIENT
class StubMappingWithScenarioJsonRecorder implements RequestListener {
private final FileSource mappingsFileSource
private final FileSource filesFileSource
private final List<CaseInsensitiveKey> headersToMatch
private IdGenerator idGenerator
private def scenariosMap
public StubMappingWithScenarioJsonRecorder(FileSource mappingsFileSource, FileSource filesFileSource, List<CaseInsensitiveKey> headersToMatch)
{
this.mappingsFileSource = mappingsFileSource
this.filesFileSource = filesFileSource
this.headersToMatch = headersToMatch
this.scenariosMap = [:]
idGenerator = new VeryShortIdGenerator()
}
@Override
public void requestReceived(Request request, Response response) {
RequestPattern requestPattern = buildRequestPatternFrom(request)
if (response.isFromProxy()) {
writeToMappingAndBodyFile(request, response, requestPattern)
}
}
private RequestPattern buildRequestPatternFrom(Request request) {
RequestPattern requestPattern = new RequestPattern(request.getMethod(), request.getUrl())
if (!headersToMatch.isEmpty()) {
for (HttpHeader header: request.getHeaders().all()) {
if (headersToMatch.contains(header.caseInsensitiveKey())) {
requestPattern.addHeader(header.key(), ValuePattern.equalTo(header.firstValue()))
}
}
}
String body = request.getBodyAsString()
if (!body.isEmpty()) {
ValuePattern bodyPattern = valuePatternForContentType(request)
requestPattern.setBodyPatterns(asList(bodyPattern))
}
return requestPattern
}
private ValuePattern valuePatternForContentType(Request request) {
String contentType = request.getHeader("Content-Type")
if (contentType != null) {
if (contentType.contains("json")) {
return ValuePattern.equalToJson(request.getBodyAsString(), LENIENT)
} else if (contentType.contains("xml")) {
return ValuePattern.equalToXml(request.getBodyAsString())
}
}
return ValuePattern.equalTo(request.getBodyAsString())
}
private void writeToMappingAndBodyFile(Request request, Response response, RequestPattern requestPattern) {
String fileId = idGenerator.generate()
String mappingFileName = UniqueFilenameGenerator.generate(request, "mapping", fileId)
String bodyFileName = UniqueFilenameGenerator.generate(request, "body", fileId)
ResponseDefinition responseToWrite = new ResponseDefinition()
responseToWrite.setStatus(response.getStatus())
responseToWrite.setBodyFileName(bodyFileName)
if (response.getHeaders().size() > 0) {
responseToWrite.setHeaders(response.getHeaders())
}
StubMapping mapping = new StubMapping(requestPattern, responseToWrite)
String scenarioName = getScenarioName(requestPattern)
def currentScenarioState = getScenarioCurrentState(scenarioName)
mapping.setScenarioName(scenarioName);
mapping.setRequiredScenarioState(currentScenarioState)
if (isNewScenarioState(scenarioName)) {
mapping.setNewScenarioState(getNewScenarioState(scenarioName))
}
filesFileSource.writeBinaryFile(bodyFileName, response.getBody())
mappingsFileSource.writeTextFile(mappingFileName, write(mapping))
}
String getScenarioName(requestPattern) {
def baseUrl = requestPattern.url.split(/[?#]/)[0]
"${requestPattern.method}_${baseUrl}"
}
String getScenarioCurrentState(String scenarioName) {
def currentState
if (!this.scenariosMap[scenarioName]) {
this.scenariosMap << [(scenarioName): Scenario.STARTED]
currentState = Scenario.STARTED
} else {
currentState = this.scenariosMap[scenarioName]
}
currentState
}
private boolean isNewScenarioState(scenarioName) {
this.scenariosMap.containsKey(scenarioName)
}
String getNewScenarioState(String scenarioName) {
def newScenarioState
if (!this.scenariosMap[scenarioName]) {
this.scenariosMap << [(scenarioName): Scenario.STARTED]
newScenarioState = Scenario.STARTED
} else {
def currentState = this.scenariosMap[scenarioName]
newScenarioState = currentState == Scenario.STARTED ? 1 : currentState + 1
this.scenariosMap[scenarioName] = newScenarioState
}
newScenarioState.toString()
}
public void setIdGenerator(IdGenerator idGenerator) {
this.idGenerator = idGenerator
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment