Compare commits

...

10 commits

Author SHA1 Message Date
Sander Hautvast
abe2f7f5ab implemented request body matching 2015-07-07 15:28:01 +02:00
Sander Hautvast
9b70d03814 readme updated 2015-06-11 16:34:35 +02:00
Sander Hautvast
1407b21b4d added json upload and response headers 2015-06-11 16:33:34 +02:00
Sander Hautvast
506bea5d0e Merge branch 'master' of https://github.com/shautvast/everest 2015-06-11 14:23:04 +02:00
Sander Hautvast
13df0260cc Update README.md 2015-06-10 12:00:50 +02:00
Sander Hautvast
82fffaae47 build fixes 2015-06-10 12:00:22 +02:00
Sander Hautvast
96fa40d4b3 Update README.md 2015-06-10 10:32:15 +02:00
Sander Hautvast
d5ba7d7ba7 Update README.md 2015-06-10 10:31:23 +02:00
Sander Hautvast
c7732f21ed Update README.md 2015-06-10 10:29:56 +02:00
Sander Hautvast
c869f65d99 Update README.md 2015-06-10 10:26:32 +02:00
21 changed files with 426 additions and 104 deletions

1
.gitignore vendored
View file

@ -5,3 +5,4 @@
/.gradle /.gradle
/.settings /.settings
/bin /bin
/everest_data

View file

@ -1,5 +1,33 @@
Simple universal mocking tool for http requests <h3>what is it?</h3>
-set up expectations using json files in $PROJECT/everest directory Simple universal mocking tool for http requests
-start using gradlew run - requires java 8
-replay - set up expectations using json files in $PROJECT/everest_data directory
- or start java with -Deverest.data=[..] for a different data directory
- start using gradlew run
- replay
<h3>Sample json</h3>
{<br/>
"name": "wehkamp.nl",<br/>
"url": "http://www.wehkamp.nl",<br/>
"method": "GET",<br/>
"requestHeaders": {<br/>
&nbsp;&nbsp;"Accept": ["application/json"]<br/>
&nbsp;&nbsp;},<br/>
"response": "<html>",<br/>
"responseStatus": 200<br/>
"responseHeaders": <br/>
&nbsp;&nbsp;"Accept": ["application/json"]<br/>
&nbsp;&nbsp;},<br/>
}<br/>
- url can be java regex expression
<h4>api for json upload</h4>
- the JSON above can be uploaded to a running server using a POST to http://[server]:[port]/__api/upload
- use Content-Type=application/json
<h3>TODO's</h3>
- reload json files on the fly
- build a proxy that generates the json from actual requests/responses

View file

@ -20,8 +20,8 @@ repositories{
} }
targetCompatibility=1.7 targetCompatibility=1.8
sourceCompatibility=1.7 sourceCompatibility=1.8
configurations { configurations {
all*.exclude group: 'commons-logging' //http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/htmlsingle/#overview-not-using-commons-logging all*.exclude group: 'commons-logging' //http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/htmlsingle/#overview-not-using-commons-logging
@ -35,6 +35,7 @@ dependencies{
compile 'org.springframework.boot:spring-boot-starter-web' compile 'org.springframework.boot:spring-boot-starter-web'
compile 'commons-io:commons-io:2.0.1' compile 'commons-io:commons-io:2.0.1'
compile 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.2.1' compile 'com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:2.2.1'
// compile 'org.littleshoot:littleproxy:1.0.0-beta7'
testCompile 'org.testng:testng:6.8' testCompile 'org.testng:testng:6.8'
testCompile "org.springframework:spring-test:4.0.6.RELEASE" testCompile "org.springframework:spring-test:4.0.6.RELEASE"
@ -43,4 +44,4 @@ dependencies{
} }
springBoot { mainClass = "nl.wehkamp.everest.App" } springBoot { mainClass = "nl.wehkamp.everest.WebServer" }

View file

@ -2,7 +2,7 @@ package nl.wehkamp.everest;
import javax.servlet.Servlet; import javax.servlet.Servlet;
import nl.wehkamp.everest.web.MockingServlet; import nl.wehkamp.everest.web.PredictableResponseServlet;
import org.springframework.beans.BeansException; import org.springframework.beans.BeansException;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
@ -30,12 +30,12 @@ public class WebServer implements ApplicationContextAware {
@Bean @Bean
public ServletRegistrationBean servletRegistrationBean() { public ServletRegistrationBean servletRegistrationBean() {
return new ServletRegistrationBean(mockingServlet(), "/*"); return new ServletRegistrationBean(predictableResponseServlet(), "/*");
} }
@Bean @Bean
public Servlet mockingServlet() { public Servlet predictableResponseServlet() {
return new MockingServlet(); return new PredictableResponseServlet();
} }
public static void main(String[] args) { public static void main(String[] args) {

View file

@ -32,15 +32,15 @@ import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
@Component("requestResponseRepository") @Component
public class RequestResponseJsonFileRepository extends RequestResponseMemoryRepository { public class PredictionJsonFileRepository extends PredictionMemoryRepository {
private static final Logger log = LoggerFactory.getLogger(RequestResponseJsonFileRepository.class); private static final Logger log = LoggerFactory.getLogger(PredictionJsonFileRepository.class);
private String dataDirectoryName = System.getProperty("everest.data", "everest_data"); private String dataDirectoryName = System.getProperty("everest.data", "everest_data");
private ObjectMapper jackson = new ObjectMapper(); private ObjectMapper jackson = new ObjectMapper();
public RequestResponseJsonFileRepository() { public PredictionJsonFileRepository() {
createDataDirectoryIfAbsent(); createDataDirectoryIfAbsent();
fillCacheIfEmpty(); fillCacheIfEmpty();
} }
@ -55,7 +55,9 @@ public class RequestResponseJsonFileRepository extends RequestResponseMemoryRepo
throw new RuntimeException(e); throw new RuntimeException(e);
} finally { } finally {
try { try {
os.close(); if (os != null) {
os.close();
}
} catch (IOException e) { } catch (IOException e) {
} }
} }
@ -79,10 +81,13 @@ public class RequestResponseJsonFileRepository extends RequestResponseMemoryRepo
try { try {
DirectoryStream<Path> directoryStream = newDirectoryStream(get(dataDirectoryName)); DirectoryStream<Path> directoryStream = newDirectoryStream(get(dataDirectoryName));
for (Path pathForJsonFile : directoryStream) { for (Path pathForJsonFile : directoryStream) {
Prediction requestResponse = readRequestResponseFromJson(pathForJsonFile); if (pathForJsonFile.toString().endsWith(".json")) {
requestResponse.setName(filename(pathForJsonFile)); log.info("reading {}", pathForJsonFile);
cache.add(requestResponse); Prediction requestResponse = readRequestResponseFromJson(pathForJsonFile);
log.info("reading {} into memory, mapping path {}", pathForJsonFile, requestResponse.getUrl()); requestResponse.setName(filename(pathForJsonFile));
cache.add(requestResponse);
log.info("reading {} into memory, mapping path {}", pathForJsonFile, requestResponse.getUrl());
}
} }
} catch (IOException x) { } catch (IOException x) {
throw new RuntimeException(x); throw new RuntimeException(x);

View file

@ -1,14 +1,15 @@
package nl.wehkamp.everest.dao; package nl.wehkamp.everest.dao;
import java.util.HashSet; import java.util.HashSet;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import nl.wehkamp.everest.model.Prediction; import nl.wehkamp.everest.model.Prediction;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@Repository("requestResponseMemoryRepository") @Repository
public class RequestResponseMemoryRepository implements RequestResponseRepository { public class PredictionMemoryRepository implements PredictionRepository {
protected Set<Prediction> cache = new HashSet<>(); protected Set<Prediction> cache = new HashSet<>();
@Override @Override
@ -24,4 +25,13 @@ public class RequestResponseMemoryRepository implements RequestResponseRepositor
public void clear() { public void clear() {
cache.clear(); cache.clear();
} }
public Optional<Prediction> findByName(String name) {
for (Prediction p : cache) {
if (p.getName().equals(name)) {
return Optional.of(p);
}
}
return Optional.empty();
}
} }

View file

@ -4,9 +4,9 @@ import java.util.Set;
import nl.wehkamp.everest.model.Prediction; import nl.wehkamp.everest.model.Prediction;
public interface RequestResponseRepository { public interface PredictionRepository {
void save(Prediction record); void save(Prediction prediction);
Set<Prediction> findAll(); Set<Prediction> findAll();

View file

@ -5,6 +5,7 @@ import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -34,6 +35,10 @@ public class Headers {
} }
} }
public Set<String> getHeaderNames() {
return headers.keySet();
}
/** /**
* returns all header values for a given name. Or null if none set * returns all header values for a given name. Or null if none set
*/ */

View file

@ -1,7 +1,10 @@
package nl.wehkamp.everest.model; package nl.wehkamp.everest.model;
import static java.util.Optional.empty;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import nl.wehkamp.everest.util.Uuids; import nl.wehkamp.everest.util.Uuids;
@ -15,12 +18,14 @@ public class Prediction {
private String url; private String url;
private String method; private String method;
private Headers requestHeaders; private Headers requestHeaders;
private String requestBody = "";
private String response; private String response;
private int responseStatus; private int responseStatus;
private Optional<Headers> responseHeaders = empty();
public boolean requestMatches(String requesturl) { public boolean requestUrlMatches(String requesturl) {
return urlPattern.matcher(requesturl).matches(); return urlPattern.matcher(requesturl).find();
} }
public Prediction() { public Prediction() {
@ -28,13 +33,15 @@ public class Prediction {
} }
private Prediction(Dto predictionDto) { private Prediction(Dto predictionDto) {
this.id = predictionDto.id; this.id = predictionDto.id != null ? predictionDto.id : Uuids.create();
this.name = predictionDto.name; this.name = predictionDto.name;
setUrl(predictionDto.url); setUrl(predictionDto.url);
this.method = predictionDto.method; this.method = predictionDto.method;
this.requestHeaders = new Headers(predictionDto.requestHeaders); this.requestHeaders = new Headers(predictionDto.requestHeaders);
this.requestBody = predictionDto.requestBody;
this.response = predictionDto.response; this.response = predictionDto.response;
this.responseStatus = predictionDto.responseStatus; this.responseStatus = predictionDto.responseStatus;
this.responseHeaders = predictionDto.getResponseHeaders() != null ? Optional.of(new Headers(predictionDto.getResponseHeaders())) : empty();
} }
public String getMethod() { public String getMethod() {
@ -89,6 +96,26 @@ public class Prediction {
this.responseStatus = responseStatus; this.responseStatus = responseStatus;
} }
public boolean hasReponseHeaders() {
return responseHeaders.isPresent();
}
public Headers getResponseHeaders() {
return responseHeaders.get();
}
public void setResponseHeaders(Headers responseHeaders) {
this.responseHeaders = Optional.ofNullable(responseHeaders);
}
public String getRequestBody() {
return requestBody;
}
public void setRequestBody(String requestBody) {
this.requestBody = requestBody;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
@ -114,7 +141,7 @@ public class Prediction {
return true; return true;
} }
public boolean containsHeaders() { public boolean containsRequestHeaders() {
return requestHeaders != null && requestHeaders.areSet(); return requestHeaders != null && requestHeaders.areSet();
} }
@ -124,7 +151,8 @@ public class Prediction {
} }
public Dto toDto() { public Dto toDto() {
return new Dto(id, name, url, method, requestHeaders.getContent(), response, responseStatus); Map<String, List<String>> responseHeaderMap = hasReponseHeaders() ? getResponseHeaders().getContent() : null;
return new Dto(id, name, url, method, requestHeaders.getContent(), response, responseStatus, responseHeaderMap);
} }
public static Prediction fromDto(Dto predictionDto) { public static Prediction fromDto(Dto predictionDto) {
@ -137,15 +165,18 @@ public class Prediction {
private String url; private String url;
private String method; private String method;
private String requestBody;
private Map<String, List<String>> requestHeaders; private Map<String, List<String>> requestHeaders;
private String response; private String response;
private int responseStatus; private int responseStatus;
private Map<String, List<String>> responseHeaders;
public Dto() { public Dto() {
} }
private Dto(String id, String name, String url, String method, Map<String, List<String>> requestHeaders, String response, int responseStatus) { private Dto(String id, String name, String url, String method, Map<String, List<String>> requestHeaders, String response, int responseStatus,
Map<String, List<String>> responseHeaders) {
super(); super();
this.id = id; this.id = id;
this.name = name; this.name = name;
@ -154,6 +185,7 @@ public class Prediction {
this.requestHeaders = requestHeaders; this.requestHeaders = requestHeaders;
this.response = response; this.response = response;
this.responseStatus = responseStatus; this.responseStatus = responseStatus;
this.responseHeaders = responseHeaders;
} }
public String getId() { public String getId() {
@ -196,6 +228,14 @@ public class Prediction {
this.requestHeaders = requestHeaders; this.requestHeaders = requestHeaders;
} }
public String getRequestBody() {
return requestBody;
}
public void setRequestBody(String requestBody) {
this.requestBody = requestBody;
}
public String getResponse() { public String getResponse() {
return response; return response;
} }
@ -212,6 +252,14 @@ public class Prediction {
this.responseStatus = responseStatus; this.responseStatus = responseStatus;
} }
public Map<String, List<String>> getResponseHeaders() {
return responseHeaders;
}
public void setResponseHeaders(Map<String, List<String>> responseHeaders) {
this.responseHeaders = responseHeaders;
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;

View file

@ -0,0 +1,29 @@
//package nl.wehkamp.everest.proxy;
//
//import io.netty.channel.ChannelHandlerContext;
//import io.netty.handler.codec.http.HttpRequest;
//
//import org.littleshoot.proxy.HttpFilters;
//import org.littleshoot.proxy.HttpFiltersAdapter;
//import org.littleshoot.proxy.HttpFiltersSourceAdapter;
//import org.littleshoot.proxy.HttpProxyServer;
//import org.littleshoot.proxy.impl.DefaultHttpProxyServer;
//
//public class Proxy {
// private int port = 8080;
// private HttpProxyServer server;
//
// public void start() {
// server = DefaultHttpProxyServer.bootstrap().withPort(port).withFiltersSource(new HttpFiltersSourceAdapter() {
// public HttpFilters filterRequest(HttpRequest originalRequest, ChannelHandlerContext ctx) {
// return new HttpFiltersAdapter(originalRequest) {
//
// };
// }
// }).start();
// }
//
// public void setPort(int port) {
// this.port = port;
// }
// }

View file

@ -0,0 +1,17 @@
package nl.wehkamp.everest.service;
import static nl.wehkamp.everest.model.Prediction.fromDto;
import java.io.IOException;
import nl.wehkamp.everest.model.Prediction;
import com.fasterxml.jackson.databind.ObjectMapper;
public class PredictionFactory {
private static ObjectMapper objectMapper = new ObjectMapper();
public static Prediction newPrediction(String json) throws IOException {
return fromDto(objectMapper.readValue(json, Prediction.Dto.class));
}
}

View file

@ -8,12 +8,14 @@
*/ */
package nl.wehkamp.everest.service; package nl.wehkamp.everest.service;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import nl.wehkamp.everest.dao.RequestResponseRepository; import nl.wehkamp.everest.dao.PredictionRepository;
import nl.wehkamp.everest.model.Prediction; import nl.wehkamp.everest.model.Prediction;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@ -25,31 +27,54 @@ import org.springframework.stereotype.Service;
@Service @Service
public class ResponseFinder { public class ResponseFinder {
@Autowired @Autowired
private RequestResponseRepository requestResponseRepository; private PredictionRepository predictionJsonFileRepository;
public Optional<Prediction> find(HttpServletRequest request) { public Optional<Prediction> find(HttpServletRequest request) {
Optional<Prediction> response = Optional.empty(); Optional<Prediction> response = Optional.empty();
Set<Prediction> all = requestResponseRepository.findAll(); Set<Prediction> all = predictionJsonFileRepository.findAll();
for (Prediction prediction : all) { for (Prediction prediction : all) {
response = matchRequestBody(request, response, prediction);
}
return response;
}
private Optional<Prediction> matchRequestBody(HttpServletRequest request, Optional<Prediction> response, Prediction prediction) {
String requestbody = getBody(request);
if (prediction.getRequestBody().equals(requestbody)) {
response = matchUrlAndMethodAndHeaders(request, response, prediction); response = matchUrlAndMethodAndHeaders(request, response, prediction);
} }
return response; return response;
} }
private Optional<Prediction> matchUrlAndMethodAndHeaders(HttpServletRequest request, Optional<Prediction> response, Prediction rr) { private Optional<Prediction> matchUrlAndMethodAndHeaders(HttpServletRequest request, Optional<Prediction> response, Prediction prediction) {
if (rr.requestMatches(request.getPathInfo())) { if (prediction.requestUrlMatches(request.getPathInfo())) {
response = matchMethodAndHeaders(request, response, rr); response = matchMethodAndHeaders(request, response, prediction);
} }
return response; return response;
} }
private Optional<Prediction> matchMethodAndHeaders(HttpServletRequest request, Optional<Prediction> response, Prediction rr) { private String getBody(HttpServletRequest request) {
if (rr.getMethod().equals(request.getMethod())) { BufferedReader reader;
if (rr.containsHeaders()) { try {
response = matchHeaders(request, response, rr); reader = request.getReader();
String line = null;
StringBuilder buffer = new StringBuilder();
while ((line = reader.readLine()) != null) {
buffer.append(line);
}
return buffer.toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private Optional<Prediction> matchMethodAndHeaders(HttpServletRequest request, Optional<Prediction> response, Prediction prediction) {
if (prediction.getMethod().equals(request.getMethod())) {
if (prediction.containsRequestHeaders()) {
response = matchHeaders(request, response, prediction);
} else { } else {
response = Optional.of(rr); response = Optional.of(prediction);
} }
} }
return response; return response;
@ -62,7 +87,7 @@ public class ResponseFinder {
return response; return response;
} }
public void setRequestResponseRepository(RequestResponseRepository requestResponseRepository) { public void setPredictionRepository(PredictionRepository predictionJsonFileRepository) {
this.requestResponseRepository = requestResponseRepository; this.predictionJsonFileRepository = predictionJsonFileRepository;
} }
} }

View file

@ -1,40 +0,0 @@
package nl.wehkamp.everest.web;
import java.io.IOException;
import java.util.Optional;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import nl.wehkamp.everest.model.Prediction;
import nl.wehkamp.everest.service.ResponseFinder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.DispatcherServlet;
/**
* Mocks http requests
*
*/
@SuppressWarnings("serial")
@Controller
public class MockingServlet extends DispatcherServlet {
@Autowired
private ResponseFinder responseFinder;
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Optional<Prediction> someRequestResponse = responseFinder.find(req);
if (someRequestResponse.isPresent()) {
Prediction requestResponse = someRequestResponse.get();
resp.getWriter().print(requestResponse.getResponse());
resp.setStatus(requestResponse.getResponseStatus());
} else {
resp.getWriter().print("Not found");
resp.setStatus(404);
}
}
}

View file

@ -0,0 +1,106 @@
package nl.wehkamp.everest.web;
import static nl.wehkamp.everest.service.PredictionFactory.newPrediction;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Optional;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import nl.wehkamp.everest.dao.PredictionRepository;
import nl.wehkamp.everest.model.Prediction;
import nl.wehkamp.everest.service.ResponseFinder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.DispatcherServlet;
/**
* Mocks http requests using prefabricated predictions
*
*/
@SuppressWarnings("serial")
@Controller
public class PredictableResponseServlet extends DispatcherServlet {
private final static Logger log = LoggerFactory.getLogger(PredictableResponseServlet.class);
@Autowired
private ResponseFinder responseFinder;
@Autowired
private PredictionRepository predictionJsonFileRepository;
@Override
protected void service(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws ServletException, IOException {
if (isUploadRequest(httpRequest)) {
handleUpload(httpRequest, httpResponse);
} else {
handleMockRequest(httpRequest, httpResponse);
}
}
private void handleMockRequest(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException {
Optional<Prediction> someRequestResponse = responseFinder.find(httpRequest);
if (someRequestResponse.isPresent()) {
Prediction prediction = someRequestResponse.get();
setPredictedResponseValues(httpResponse, prediction);
} else {
httpResponse.getWriter().print("Not found");
httpResponse.setStatus(404);
}
}
private void setPredictedResponseValues(HttpServletResponse httpResponse, Prediction prediction) throws IOException {
httpResponse.getWriter().print(prediction.getResponse());
httpResponse.setStatus(prediction.getResponseStatus());
if (prediction.hasReponseHeaders()) {
setPredictedResponseHeaders(httpResponse, prediction);
}
}
private void setPredictedResponseHeaders(HttpServletResponse httpResponse, Prediction prediction) {
for (String headername : prediction.getResponseHeaders().getHeaderNames()) {
for (String headervalue : prediction.getResponseHeaders().getAll(headername)) {
httpResponse.addHeader(headername, headervalue);
}
}
}
private void handleUpload(HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException {
try {
predictionJsonFileRepository.save(newPrediction(readJsonFromHttpBody(httpRequest)));
httpResponse.setStatus(201);
} catch (IOException e) {
httpResponse.setStatus(500);
httpResponse.getWriter().print(e.getClass().getName() + ":" + e.getMessage());
}
}
private String readJsonFromHttpBody(HttpServletRequest httprequest) throws IOException {
BufferedReader reader = httprequest.getReader();
String line;
StringBuilder builder = new StringBuilder();
while ((line = reader.readLine()) != null) {
builder.append(line);
}
String json = builder.toString();
log.info("upload of json {}", json);
return json;
}
private boolean isUploadRequest(HttpServletRequest req) {
return req.getMethod().equals("POST") && req.getPathInfo().startsWith("/__api/upload") && req.getHeader("Content-Type").equals("application/json");
}
public void setPredictionRepository(PredictionRepository predictionJsonFileRepository) {
this.predictionJsonFileRepository = predictionJsonFileRepository;
}
}

View file

@ -11,6 +11,7 @@ import java.util.List;
import nl.wehkamp.everest.model.Headers; import nl.wehkamp.everest.model.Headers;
import nl.wehkamp.everest.model.Prediction; import nl.wehkamp.everest.model.Prediction;
import nl.wehkamp.everest.util.FileLoader;
import nl.wehkamp.everest.util.Uuids; import nl.wehkamp.everest.util.Uuids;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
@ -21,7 +22,7 @@ public class RecordRepositoryTest {
@AfterMethod @AfterMethod
public void teardown() throws IOException { public void teardown() throws IOException {
Uuids.removeTestValue(); Uuids.removeTestValue();
Files.delete(Paths.get("everest_data", "wehkamp.nl.json")); // Files.delete(Paths.get("everest_data", "wehkamp.nl.json"));
} }
@Test @Test
@ -37,15 +38,13 @@ public class RecordRepositoryTest {
record.setHeaders(headers); record.setHeaders(headers);
record.setResponseStatus(200); record.setResponseStatus(200);
record.setResponse("<html>"); record.setResponse("<html>");
new RequestResponseJsonFileRepository().save(record); new PredictionJsonFileRepository().save(record);
List<String> lines = Files.readAllLines(Paths.get("everest_data", "wehkamp.nl.json"), StandardCharsets.UTF_8); List<String> lines = Files.readAllLines(Paths.get("everest_data", "wehkamp.nl.json"), StandardCharsets.UTF_8);
assertFalse(lines.isEmpty()); assertFalse(lines.isEmpty());
System.out.println(lines.get(0)); System.out.println(lines.get(0));
assertEquals( assertEquals(lines.get(0), FileLoader.load("test.json"));
lines.get(0),
"{\"id\":\"91f83cd9-a0a5-49f5-b740-78ba8f504797\",\"name\":\"wehkamp.nl\",\"url\":\"http://www.wehkamp.nl\",\"method\":\"GET\",\"requestHeaders\":{\"Accept\":[\"application/json\"]},\"response\":\"<html>\",\"responseStatus\":200}");
} }
} }

View file

@ -0,0 +1,16 @@
package nl.wehkamp.everest.util;
import java.io.IOException;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.ClassPathResource;
public class FileLoader {
public static String load(String resource) {
try {
return IOUtils.toString(new ClassPathResource(resource).getInputStream());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -1,21 +1,24 @@
package nl.wehkamp.everest.web; package nl.wehkamp.everest.util;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Map; import java.util.Map;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
public class TestClient { public class TestClient {
private static HttpClient httpclient = HttpClients.createDefault(); private static HttpClient httpclient = HttpClients.createDefault();
private static HttpHost target = new HttpHost("localhost", 8080, "http"); private static HttpHost target = new HttpHost("localhost", 8080, "http");
public static String get(String url) { public static String httpGet(String url) {
try { try {
HttpGet httpGet = new HttpGet(url); HttpGet httpGet = new HttpGet(url);
HttpResponse httpResponse = httpclient.execute(target, httpGet); HttpResponse httpResponse = httpclient.execute(target, httpGet);
@ -26,7 +29,7 @@ public class TestClient {
} }
} }
public static String get(String url, Map<String, String> headers) { public static String httpGet(String url, Map<String, String> headers) {
HttpGet httpGet = new HttpGet(url); HttpGet httpGet = new HttpGet(url);
for (Map.Entry<String, String> header : headers.entrySet()) { for (Map.Entry<String, String> header : headers.entrySet()) {
httpGet.addHeader(header.getKey(), header.getValue()); httpGet.addHeader(header.getKey(), header.getValue());
@ -40,9 +43,21 @@ public class TestClient {
} }
} }
public static String post(String url, String postBody) { public static String httpPost(String url, String postBody) {
try { try {
HttpPost httpPost = new HttpPost(url); HttpPost httpPost = createPost(url, postBody, null);
HttpResponse httpResponse = httpclient.execute(target, httpPost);
String responseBody = IOUtils.toString(httpResponse.getEntity().getContent());
return httpResponse.getStatusLine().getStatusCode() + ":" + responseBody;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String httpPost(String url, String postBody, Map<String, String> headers) {
try {
HttpPost httpPost = createPost(url, postBody, headers);
HttpResponse httpResponse = httpclient.execute(target, httpPost); HttpResponse httpResponse = httpclient.execute(target, httpPost);
String body = IOUtils.toString(httpResponse.getEntity().getContent()); String body = IOUtils.toString(httpResponse.getEntity().getContent());
return httpResponse.getStatusLine().getStatusCode() + ":" + body; return httpResponse.getStatusLine().getStatusCode() + ":" + body;
@ -50,4 +65,17 @@ public class TestClient {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
private static HttpPost createPost(String url, String postBody, Map<String, String> headers) throws UnsupportedEncodingException {
HttpPost httpPost = new HttpPost(url);
HttpEntity entity = new ByteArrayEntity(postBody.getBytes("UTF-8"));
httpPost.setEntity(entity);
if (headers != null) {
for (Map.Entry<String, String> header : headers.entrySet()) {
httpPost.addHeader(header.getKey(), header.getValue());
}
}
return httpPost;
}
} }

View file

@ -1,11 +1,11 @@
package nl.wehkamp.everest.web; package nl.wehkamp.everest.web;
import static java.util.Collections.singletonMap; import static java.util.Collections.singletonMap;
import static nl.wehkamp.everest.web.TestClient.get; import static nl.wehkamp.everest.util.TestClient.httpGet;
import static nl.wehkamp.everest.web.TestClient.post; import static nl.wehkamp.everest.util.TestClient.httpPost;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import nl.wehkamp.everest.WebServer; import nl.wehkamp.everest.WebServer;
import nl.wehkamp.everest.dao.RequestResponseMemoryRepository; import nl.wehkamp.everest.dao.PredictionMemoryRepository;
import nl.wehkamp.everest.model.Prediction; import nl.wehkamp.everest.model.Prediction;
import nl.wehkamp.everest.service.ResponseFinder; import nl.wehkamp.everest.service.ResponseFinder;
@ -18,14 +18,14 @@ import org.testng.annotations.Test;
*/ */
public class MockingServletTests { public class MockingServletTests {
private RequestResponseMemoryRepository requestResponseRepository; private PredictionMemoryRepository requestResponseRepository;
@BeforeSuite @BeforeSuite
public void setup() { public void setup() {
WebServer.start(); WebServer.start();
ResponseFinder responseFinder = WebServer.instance.getBean(ResponseFinder.class); ResponseFinder responseFinder = WebServer.instance.getBean(ResponseFinder.class);
requestResponseRepository = new RequestResponseMemoryRepository(); requestResponseRepository = new PredictionMemoryRepository();
responseFinder.setRequestResponseRepository(requestResponseRepository); responseFinder.setPredictionRepository(requestResponseRepository);
} }
@AfterMethod @AfterMethod
@ -41,7 +41,7 @@ public class MockingServletTests {
record.setResponse("get successful"); record.setResponse("get successful");
record.setResponseStatus(200); record.setResponseStatus(200);
requestResponseRepository.save(record); requestResponseRepository.save(record);
assertEquals(get("/testget"), "200:get successful"); assertEquals(httpGet("/testget"), "200:get successful");
} }
@Test @Test
@ -53,7 +53,7 @@ public class MockingServletTests {
record.setResponse("getWithHeader successful"); record.setResponse("getWithHeader successful");
record.setResponseStatus(200); record.setResponseStatus(200);
requestResponseRepository.save(record); requestResponseRepository.save(record);
assertEquals(get("/testget", singletonMap("Content-Type", "application/json")), "200:getWithHeader successful"); assertEquals(httpGet("/testget", singletonMap("Content-Type", "application/json")), "200:getWithHeader successful");
} }
@Test @Test
@ -65,7 +65,7 @@ public class MockingServletTests {
record.setResponse("getWithHeader successful"); record.setResponse("getWithHeader successful");
record.setResponseStatus(200); record.setResponseStatus(200);
requestResponseRepository.save(record); requestResponseRepository.save(record);
assertEquals(get("/testget", singletonMap("Content-Type", "application/json")), "404:Not found"); assertEquals(httpGet("/testget", singletonMap("Content-Type", "application/json")), "404:Not found");
} }
@Test @Test
@ -76,7 +76,7 @@ public class MockingServletTests {
record.setResponse("get wildcard successful"); record.setResponse("get wildcard successful");
record.setResponseStatus(200); record.setResponseStatus(200);
requestResponseRepository.save(record); requestResponseRepository.save(record);
assertEquals(get("/testget/foo"), "200:get wildcard successful"); assertEquals(httpGet("/testget/foo"), "200:get wildcard successful");
} }
@Test @Test
@ -87,6 +87,6 @@ public class MockingServletTests {
record.setResponse("post successful"); record.setResponse("post successful");
record.setResponseStatus(200); record.setResponseStatus(200);
requestResponseRepository.save(record); requestResponseRepository.save(record);
assertEquals(post("/testpost", "body"), "200:post successful"); assertEquals(httpPost("/testpost", "body"), "200:post successful");
} }
} }

View file

@ -0,0 +1,42 @@
package nl.wehkamp.everest.web;
import static java.util.Collections.singletonMap;
import static nl.wehkamp.everest.util.FileLoader.load;
import static nl.wehkamp.everest.util.TestClient.httpPost;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import java.util.Optional;
import nl.wehkamp.everest.WebServer;
import nl.wehkamp.everest.dao.PredictionMemoryRepository;
import nl.wehkamp.everest.model.Prediction;
import nl.wehkamp.everest.service.ResponseFinder;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
public class UploadTests {
private PredictionMemoryRepository predictionMemoryRepository;
@BeforeSuite
public void setup() {
WebServer.start();
ResponseFinder responseFinder = WebServer.instance.getBean(ResponseFinder.class);
predictionMemoryRepository = new PredictionMemoryRepository();
responseFinder.setPredictionRepository(predictionMemoryRepository);
PredictableResponseServlet servlet = WebServer.instance.getBean(PredictableResponseServlet.class);
servlet.setPredictionRepository(predictionMemoryRepository);
predictionMemoryRepository.clear();
}
@Test
public void test() {
httpPost("/__api/upload", load("uploadtest.json"), singletonMap("Content-Type", "application/json"));
Optional<Prediction> prediction = predictionMemoryRepository.findByName("test.nl");
assertTrue(prediction.isPresent());
assertEquals(prediction.get().getUrl(), "/entry");
}
}

View file

@ -0,0 +1 @@
{"id":"91f83cd9-a0a5-49f5-b740-78ba8f504797","name":"wehkamp.nl","url":"http://www.wehkamp.nl","method":"GET","requestHeaders":{"Accept":["application/json"]},"response":"<html>","responseStatus":200,"responseHeaders":null}

View file

@ -0,0 +1 @@
{"id":"1","name":"test.nl","url":"/entry","method":"GET","requestHeaders":{"Accept":["application/json"]},"response":"<html>","responseStatus":200,"responseHeaders":null}