From afe39d27937e7821938364102265b67e7e6255f0 Mon Sep 17 00:00:00 2001 From: sergio mena doce Date: Sat, 11 Nov 2023 13:01:15 +0100 Subject: [PATCH] Issue 2443: karate mock server interceptor --- .../java/com/intuit/karate/core/MockHandler.java | 12 +++++++++--- .../com/intuit/karate/core/MockInterceptor.java | 11 +++++++++++ .../java/com/intuit/karate/core/MockServer.java | 16 ++++++++++++---- .../com/intuit/karate/core/mock/MockTest.java | 13 +++++++++++-- 4 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 karate-core/src/main/java/com/intuit/karate/core/MockInterceptor.java diff --git a/karate-core/src/main/java/com/intuit/karate/core/MockHandler.java b/karate-core/src/main/java/com/intuit/karate/core/MockHandler.java index a98517bfc..b0e7664e2 100644 --- a/karate-core/src/main/java/com/intuit/karate/core/MockHandler.java +++ b/karate-core/src/main/java/com/intuit/karate/core/MockHandler.java @@ -77,20 +77,23 @@ public class MockHandler implements ServerHandler { protected static final ThreadLocal LOCAL_REQUEST = new ThreadLocal<>(); private final String prefix; + private final MockInterceptor mockInterceptor; + public MockHandler(Feature feature) { this(feature, null); } public MockHandler(Feature feature, Map args) { - this(null, Collections.singletonList(feature), args); + this(null, Collections.singletonList(feature), args, null); } public MockHandler(List features) { - this(null, features, null); + this(null, features, null, null); } - public MockHandler(String prefix, List features, Map args) { + public MockHandler(String prefix, List features, Map 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(); @@ -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; } } diff --git a/karate-core/src/main/java/com/intuit/karate/core/MockInterceptor.java b/karate-core/src/main/java/com/intuit/karate/core/MockInterceptor.java new file mode 100644 index 000000000..6edfa6845 --- /dev/null +++ b/karate-core/src/main/java/com/intuit/karate/core/MockInterceptor.java @@ -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); + +} \ No newline at end of file diff --git a/karate-core/src/main/java/com/intuit/karate/core/MockServer.java b/karate-core/src/main/java/com/intuit/karate/core/MockServer.java index f055cc0f5..633dfef0d 100644 --- a/karate-core/src/main/java/com/intuit/karate/core/MockServer.java +++ b/karate-core/src/main/java/com/intuit/karate/core/MockServer.java @@ -68,6 +68,7 @@ public static class Builder { File keyFile; Map args; String prefix = null; + MockInterceptor interceptor = null; public Builder watch(boolean value) { watch = value; @@ -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); @@ -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); @@ -143,15 +149,17 @@ private static class ReloadingMockHandler implements ServerHandler { private MockHandler handler; private final LinkedHashMap files = new LinkedHashMap<>(); private final String prefix; + private final MockInterceptor interceptor; - public ReloadingMockHandler(List features, Map args, String prefix) { + public ReloadingMockHandler(List features, Map 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 @@ -159,7 +167,7 @@ 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 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); } diff --git a/karate-core/src/test/java/com/intuit/karate/core/mock/MockTest.java b/karate-core/src/test/java/com/intuit/karate/core/mock/MockTest.java index 134e2fba7..89645e875 100644 --- a/karate-core/src/test/java/com/intuit/karate/core/mock/MockTest.java +++ b/karate-core/src/test/java/com/intuit/karate/core/mock/MockTest.java @@ -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; @@ -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; @@ -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); } }