Skip to content

Commit

Permalink
Merge pull request #2445 from sergy8612/mock-server-interceptor
Browse files Browse the repository at this point in the history
Issue 2443: karate mock server interceptor
  • Loading branch information
ptrthomas authored Nov 15, 2023
2 parents 71b3140 + afe39d2 commit f6e8762
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,20 +77,23 @@ public class MockHandler implements ServerHandler {
protected static final ThreadLocal<Request> LOCAL_REQUEST = new ThreadLocal<>();
private final String prefix;

private final MockInterceptor mockInterceptor;

public MockHandler(Feature feature) {
this(feature, null);
}

public MockHandler(Feature feature, Map<String, Object> args) {
this(null, Collections.singletonList(feature), args);
this(null, Collections.singletonList(feature), args, null);
}

public MockHandler(List<Feature> features) {
this(null, features, null);
this(null, features, null, null);
}

public MockHandler(String prefix, List<Feature> features, Map<String, Object> args) {
public MockHandler(String prefix, List<Feature> features, Map<String, Object> args, MockInterceptor interceptor) {
this.prefix = "/".equals(prefix) ? null : prefix;
this.mockInterceptor = interceptor;
features.forEach(feature -> {
ScenarioRuntime runtime = initRuntime(feature, args);
corsEnabled = corsEnabled || runtime.engine.getConfig().isCorsEnabled();
Expand Down Expand Up @@ -225,6 +228,9 @@ public synchronized Response handle(Request req) { // note the [synchronized]
if (prevEngine != null) {
ScenarioEngine.set(prevEngine);
}
if (mockInterceptor != null) {
mockInterceptor.intercept(req, res, scenario);
}
return res;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.intuit.karate.core;

import com.intuit.karate.http.Request;
import com.intuit.karate.http.Response;

@FunctionalInterface
public interface MockInterceptor {

void intercept(Request req, Response res, Scenario scenario);

}
16 changes: 12 additions & 4 deletions karate-core/src/main/java/com/intuit/karate/core/MockServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public static class Builder {
File keyFile;
Map<String, Object> args;
String prefix = null;
MockInterceptor interceptor = null;

public Builder watch(boolean value) {
watch = value;
Expand Down Expand Up @@ -116,6 +117,11 @@ public Builder arg(String name, Object value) {
return this;
}

public Builder interceptor(MockInterceptor value) {
interceptor = value;
return this;
}

public MockServer build() {
ServerBuilder sb = Server.builder();
sb.requestTimeoutMillis(0);
Expand All @@ -129,7 +135,7 @@ public MockServer build() {
} else {
sb.http(port);
}
ServerHandler handler = watch ? new ReloadingMockHandler(features, args, prefix) : new MockHandler(prefix, features, args);
ServerHandler handler = watch ? new ReloadingMockHandler(features, args, prefix, interceptor) : new MockHandler(prefix, features, args, interceptor);
HttpService service = new HttpServerHandler(handler);
sb.service("prefix:" + (prefix == null ? "/" : prefix), service);
return new MockServer(sb);
Expand All @@ -143,23 +149,25 @@ private static class ReloadingMockHandler implements ServerHandler {
private MockHandler handler;
private final LinkedHashMap<File, Long> files = new LinkedHashMap<>();
private final String prefix;
private final MockInterceptor interceptor;

public ReloadingMockHandler(List<Feature> features, Map<String, Object> args, String prefix) {
public ReloadingMockHandler(List<Feature> features, Map<String, Object> args, String prefix, MockInterceptor interceptor) {
this.args = args;
this.prefix = prefix;
this.interceptor = interceptor;
for (Feature f : features) {
this.files.put(f.getResource().getFile(), f.getResource().getFile().lastModified());
}
logger.debug("watch mode init - {}", files);
handler = new MockHandler(prefix, features, args);
handler = new MockHandler(prefix, features, args, this.interceptor);
}

@Override
public Response handle(Request request) {
boolean reload = files.entrySet().stream().reduce(false, (modified, entry) -> entry.getKey().lastModified() > entry.getValue(), (a, b) -> a || b);
if (reload) {
List<Feature> features = files.keySet().stream().map(f -> Feature.read(f)).collect(Collectors.toList());
handler = new MockHandler(prefix, features, args);
handler = new MockHandler(prefix, features, args, interceptor);
}
return handler.handle(request);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.intuit.karate.core.mock;

import com.intuit.karate.http.HttpServer;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

import com.intuit.karate.Results;
import com.intuit.karate.Runner;
import com.intuit.karate.core.MockServer;
import static org.junit.jupiter.api.Assertions.*;
import com.intuit.karate.http.HttpServer;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
Expand All @@ -18,11 +21,16 @@ class MockTest {

static final Logger logger = LoggerFactory.getLogger(MockTest.class);

static final AtomicInteger count = new AtomicInteger(0);

static HttpServer startMockServer() {
MockServer server = MockServer.featurePaths(
"classpath:com/intuit/karate/core/mock/_simple.feature",
"classpath:com/intuit/karate/core/mock/_mock.feature")
.pathPrefix("/") // ensure cli default works
.interceptor((req, res, scenario) ->
logger.debug("interceptor has been called %s times"
.formatted(count.incrementAndGet())))
.build();
System.setProperty("karate.server.port", server.getPort() + "");
return server;
Expand All @@ -39,6 +47,7 @@ void testMock() {
.configDir("classpath:com/intuit/karate/core/mock")
.parallel(1);
assertEquals(0, results.getFailCount(), results.getErrorMessages());
assertTrue(count.get() > 0);
}

}

0 comments on commit f6e8762

Please sign in to comment.