package combo; import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder; import com.github.tomakehurst.wiremock.stubbing.Scenario; import com.google.gson.Gson; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; import java.util.*; import static com.github.tomakehurst.wiremock.client.WireMock.*; import static java.lang.String.format; public final class ComboServerRule implements TestRule { private final WireMockServer server; public ComboServerRule(final int port) { this.server = new WireMockServer(port); } @Override public Statement apply(final Statement base, final Description description) { return new Statement() { @Override public void evaluate() throws Throwable { try { server.start(); base.evaluate(); } finally { server.stop(); } } }; } public ComboServerResponseStep whenTopicIsSubscribedTo(final String topicName) { return (response, restOfTheResponses) -> server.givenThat(post(urlEqualTo(format("/topics/%s/subscriptions", topicName))) .willReturn(response.responseDefinitionBuilder)); } public ComboServerResponseStep whenNextFactIsRequested(final String topicName, final String subscriptionId) { return (response, restOfTheResponses) -> { int i = 0; for (final ComboServerResponse nextResponse : combine(response, restOfTheResponses)) { server.givenThat(get(urlEqualTo(format("/topics/%s/subscriptions/%s/next", topicName, subscriptionId))) .inScenario("sequence_of_responses") .whenScenarioStateIs(i == 0 ? Scenario.STARTED : "response_" + (i - 1)) .willReturn(nextResponse.responseDefinitionBuilder) .willSetStateTo("response_" + i)); i = i + 1; } }; } public ComboServerResponseStep whenFactIsPublished(final String topicName) { return (response, restOfTheResponses) -> server.givenThat(post(urlEqualTo(format("/topics/%s/facts", topicName))) .willReturn(response.responseDefinitionBuilder)); } public void verifyFactWasPublished(final String topicName) { server.verify(postRequestedFor(urlEqualTo(format("/topics/%s/facts", topicName)))); } public interface ComboServerResponseStep { void thenRespondWith(ComboServerResponse response, ComboServerResponse... restOfTheResponses); } public static final class ComboServerResponse { private final ResponseDefinitionBuilder responseDefinitionBuilder; private ComboServerResponse(final ResponseDefinitionBuilder responseDefinitionBuilder) { this.responseDefinitionBuilder = responseDefinitionBuilder; } public static ComboServerResponse subscriptionWithId(final String subscriptionId) { return new ComboServerResponse(aResponse() .withHeader(Header.Keys.CONTENT_TYPE, Header.ContentType.JSON) .withBody(subscriptionAsJson(subscriptionId))); } public static ComboServerResponse fact(final Object fact) { return new ComboServerResponse(aResponse() .withHeader(Header.Keys.CONTENT_TYPE, Header.ContentType.JSON) .withBody(new Gson().toJson(fact))); } public static ComboServerResponse ok() { return new ComboServerResponse(aResponse().withStatus(HttpStatus.OK)); } public static ComboServerResponse noContent() { return new ComboServerResponse(aResponse().withStatus(HttpStatus.NO_CONTENT)); } public static ComboServerResponse badRequest() { return new ComboServerResponse(aResponse().withStatus(HttpStatus.BAD_REQUEST)); } private static String subscriptionAsJson(final String subscriptionId) { final Map<String, Object> subscriptionAsJson = new HashMap<>(); subscriptionAsJson.put("subscription_id", subscriptionId); return new Gson().toJson(subscriptionAsJson); } } @SuppressWarnings("unchecked") private static <T> List<T> combine(final T firstT, final T... restOfTheTs) { final List<T> allTheTs = new ArrayList<>(Arrays.asList(restOfTheTs)); allTheTs.add(0, firstT); return allTheTs; } static final class Header { static final class Keys { static final String CONTENT_TYPE = "Content-Type"; } static final class ContentType { static final String JSON = "application/json"; } } static final class HttpStatus { static final int OK = 200; static final int BAD_REQUEST = 400; static final int NO_CONTENT = 204; } }