All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.mockserver.mock.Expectation Maven / Gradle / Ivy

There is a newer version: 5.15.0
Show newest version
package org.mockserver.mock;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.mockserver.matchers.TimeToLive;
import org.mockserver.matchers.Times;
import org.mockserver.model.*;
import org.mockserver.uuid.UUIDService;

import java.util.Comparator;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;

import static org.mockserver.model.OpenAPIDefinition.openAPI;

/**
 * @author jamesdbloom
 */
@SuppressWarnings("rawtypes")
public class Expectation extends ObjectWithJsonToString {

    private static final String[] excludedFields = {"id", "created"};
    private static final AtomicInteger EXPECTATION_COUNTER = new AtomicInteger(0);
    private static final long START_TIME = System.currentTimeMillis();
    private int hashCode;
    private String id;
    @JsonIgnore
    private long created;
    private final Integer priority;
    private final RequestDefinition httpRequest;
    private final Times times;
    private final TimeToLive timeToLive;
    private HttpResponse httpResponse;
    private HttpTemplate httpResponseTemplate;
    private HttpClassCallback httpResponseClassCallback;
    private HttpObjectCallback httpResponseObjectCallback;
    private HttpForward httpForward;
    private HttpTemplate httpForwardTemplate;
    private HttpClassCallback httpForwardClassCallback;
    private HttpObjectCallback httpForwardObjectCallback;
    private HttpOverrideForwardedRequest httpOverrideForwardedRequest;
    private HttpError httpError;

    public static final Comparator EXPECTATION_PRIORITY_COMPARATOR = Comparator
        .comparing(Expectation::getPriority, Comparator.nullsLast(Comparator.reverseOrder()))
        .thenComparing(Expectation::getCreated, Comparator.nullsLast(Comparator.naturalOrder()));

    /**
     * Specify the OpenAPI and operationId to match against by URL or payload and string as follows:
     * 

     *   // Create from a publicly hosted HTTP location (json or yaml)
     *   when("https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore-expanded.yaml", "showPetById")
     *
     *   // Create from a file on the local filesystem (json or yaml)
     *   when("file://Users/myuser/git/mockserver/mockserver-core/src/test/resources/org/mockserver/mock/openapi_petstore_example.json", "showPetById");
     *
     *   // Create from a classpath resource in the /api package (json or yaml)
     *   when("org/mockserver/mock/openapi_petstore_example.json", "showPetById");
     *
     *   // Create from an OpenAPI payload (json or yaml)
     *   when("{\"openapi\": \"3.0.0\", \"info\": { ...", "showPetById")
     * 

* * @param specUrlOrPayload the OpenAPI to match against by URL or payload * @param operationId operationId from the OpenAPI to match against i.e. "showPetById" * @return the Expectation */ public static Expectation when(String specUrlOrPayload, String operationId) { return new Expectation(openAPI(specUrlOrPayload, operationId)); } /** * Specify the OpenAPI and operationId to match against by URL or payload and string with a match priority as follows: *

     *   // Create from a publicly hosted HTTP location (json or yaml)
     *   when("https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore-expanded.yaml", "showPetById", 10)
     *
     *   // Create from a file on the local filesystem (json or yaml)
     *   when("file://Users/myuser/git/mockserver/mockserver-core/src/test/resources/org/mockserver/mock/openapi_petstore_example.json", "showPetById", 10);
     *
     *   // Create from a classpath resource in the /api package (json or yaml)
     *   when("org/mockserver/mock/openapi_petstore_example.json", "showPetById", 10);
     *
     *   // Create from an OpenAPI payload (json or yaml)
     *   when("{\"openapi\": \"3.0.0\", \"info\": { ...", "showPetById", 10)
     * 

* * @param specUrlOrPayload the OpenAPI to match against by URL or payload * @param operationId operationId from the OpenAPI to match against i.e. "showPetById" * @param priority the priority with which this expectation is used to match requests compared to other expectations (high first) * @return the Expectation */ public static Expectation when(String specUrlOrPayload, String operationId, Integer priority) { return new Expectation(openAPI(specUrlOrPayload, operationId), Times.unlimited(), TimeToLive.unlimited(), priority); } /** * Specify the OpenAPI and operationId to match against by URL or payload and string for a limit number of times or time as follows: *

     *   // Create from a publicly hosted HTTP location (json or yaml)
     *   when("https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore-expanded.yaml", "showPetById", 5, exactly(TimeUnit.SECONDS, 90))
     *
     *   // Create from a file on the local filesystem (json or yaml)
     *   when("file://Users/myuser/git/mockserver/mockserver-core/src/test/resources/org/mockserver/mock/openapi_petstore_example.json", "showPetById", 5, exactly(TimeUnit.SECONDS, 90));
     *
     *   // Create from a classpath resource in the /api package (json or yaml)
     *   when("org/mockserver/mock/openapi_petstore_example.json", "showPetById", 5, exactly(TimeUnit.SECONDS, 90));
     *
     *   // Create from an OpenAPI payload (json or yaml)
     *   when("{\"openapi\": \"3.0.0\", \"info\": { ...", "showPetById", 5, exactly(TimeUnit.SECONDS, 90))
     * 

* * @param specUrlOrPayload the OpenAPI to match against by URL or payload * @param operationId operationId from the OpenAPI to match against i.e. "showPetById" * @param times the number of times to use this expectation to match requests * @param timeToLive the time this expectation should be used to match requests * @return the Expectation */ public static Expectation when(String specUrlOrPayload, String operationId, Times times, TimeToLive timeToLive) { return new Expectation(openAPI(specUrlOrPayload, operationId), times, timeToLive, 0); } /** * Specify the OpenAPI and operationId to match against by URL or payload and string for a limit number of times or time and a match priority as follows: *

     *   // Create from a publicly hosted HTTP location (json or yaml)
     *   when("https://raw.githubusercontent.com/OAI/OpenAPI-Specification/master/examples/v3.0/petstore-expanded.yaml", "showPetById", 5, exactly(TimeUnit.SECONDS, 90))
     *
     *   // Create from a file on the local filesystem (json or yaml)
     *   when("file://Users/myuser/git/mockserver/mockserver-core/src/test/resources/org/mockserver/mock/openapi_petstore_example.json", "showPetById", 5, exactly(TimeUnit.SECONDS, 90));
     *
     *   // Create from a classpath resource in the /api package (json or yaml)
     *   when("org/mockserver/mock/openapi_petstore_example.json", "showPetById", 5, exactly(TimeUnit.SECONDS, 90));
     *
     *   // Create from an OpenAPI payload (json or yaml)
     *   when("{\"openapi\": \"3.0.0\", \"info\": { ...", "showPetById", 5, exactly(TimeUnit.SECONDS, 90))
     * 

* * @param specUrlOrPayload the OpenAPI to match against by URL or payload * @param operationId operationId from the OpenAPI to match against i.e. "showPetById" * @param times the number of times to use this expectation to match requests * @param timeToLive the time this expectation should be used to match requests * @param priority the priority with which this expectation is used to match requests compared to other expectations (high first) * @return the Expectation */ public static Expectation when(String specUrlOrPayload, String operationId, Times times, TimeToLive timeToLive, Integer priority) { return new Expectation(openAPI(specUrlOrPayload, operationId), times, timeToLive, priority); } /** * Specify the HttpRequest to match against as follows: *

     *     when(
     *         request()
     *             .withMethod("GET")
     *             .withPath("/some/path")
     *     ).thenRespond(
     *         response()
     *             .withContentType(APPLICATION_JSON_UTF_8)
     *             .withBody("{\"some\": \"body\"}")
     *     );
     * 

* * @param httpRequest the HttpRequest to match against * @return the Expectation */ public static Expectation when(HttpRequest httpRequest) { return new Expectation(httpRequest); } /** * Specify the HttpRequest to match against with a match priority as follows: *

     *     when(
     *         request()
     *             .withMethod("GET")
     *             .withPath("/some/path"),
     *         10
     *     ).thenRespond(
     *         response()
     *             .withContentType(APPLICATION_JSON_UTF_8)
     *             .withBody("{\"some\": \"body\"}")
     *     );
     * 

* * @param httpRequest the HttpRequest to match against * @param priority the priority with which this expectation is used to match requests compared to other expectations (high first) * @return the Expectation */ public static Expectation when(HttpRequest httpRequest, Integer priority) { return new Expectation(httpRequest, Times.unlimited(), TimeToLive.unlimited(), priority); } /** * Specify the HttpRequest to match against for a limit number of times or time as follows: *

     *     when(
     *         request()
     *             .withMethod("GET")
     *             .withPath("/some/path"),
     *         5,
     *         exactly(TimeUnit.SECONDS, 90)
     *     ).thenRespond(
     *         response()
     *             .withContentType(APPLICATION_JSON_UTF_8)
     *             .withBody("{\"some\": \"body\"}")
     *     );
     * 

* * @param httpRequest the HttpRequest to match against * @param times the number of times to use this expectation to match requests * @param timeToLive the time this expectation should be used to match requests * @return the Expectation */ public static Expectation when(HttpRequest httpRequest, Times times, TimeToLive timeToLive) { return new Expectation(httpRequest, times, timeToLive, 0); } /** * Specify the HttpRequest to match against for a limit number of times or time and a match priority as follows: *

     *     when(
     *         request()
     *             .withMethod("GET")
     *             .withPath("/some/path"),
     *         5,
     *         exactly(TimeUnit.SECONDS, 90),
     *         10
     *     ).thenRespond(
     *         response()
     *             .withContentType(APPLICATION_JSON_UTF_8)
     *             .withBody("{\"some\": \"body\"}")
     *     );
     * 

* * @param httpRequest the HttpRequest to match against * @param times the number of times to use this expectation to match requests * @param timeToLive the time this expectation should be used to match requests * @param priority the priority with which this expectation is used to match requests compared to other expectations (high first) * @return the Expectation */ public static Expectation when(HttpRequest httpRequest, Times times, TimeToLive timeToLive, Integer priority) { return new Expectation(httpRequest, times, timeToLive, priority); } public Expectation(RequestDefinition requestDefinition) { this(requestDefinition, Times.unlimited(), TimeToLive.unlimited(), 0); } public Expectation(RequestDefinition requestDefinition, Times times, TimeToLive timeToLive, Integer priority) { // ensure created enforces insertion order by relying on system time, and a counter EXPECTATION_COUNTER.compareAndSet(Integer.MAX_VALUE, 0); this.created = System.currentTimeMillis() - START_TIME + EXPECTATION_COUNTER.incrementAndGet(); this.httpRequest = requestDefinition; this.times = times; this.timeToLive = timeToLive; this.priority = priority; } public Expectation withId(String key) { this.id = key; return this; } public String getId() { if (id == null) { withId(UUIDService.getUUID()); } return id; } public Integer getPriority() { return priority; } public Expectation withCreated(long created) { this.created = created; return this; } public long getCreated() { return created; } public RequestDefinition getHttpRequest() { return httpRequest; } public HttpResponse getHttpResponse() { return httpResponse; } public HttpTemplate getHttpResponseTemplate() { return httpResponseTemplate; } public HttpClassCallback getHttpResponseClassCallback() { return httpResponseClassCallback; } public HttpObjectCallback getHttpResponseObjectCallback() { return httpResponseObjectCallback; } public HttpForward getHttpForward() { return httpForward; } public HttpTemplate getHttpForwardTemplate() { return httpForwardTemplate; } public HttpClassCallback getHttpForwardClassCallback() { return httpForwardClassCallback; } public HttpObjectCallback getHttpForwardObjectCallback() { return httpForwardObjectCallback; } public HttpOverrideForwardedRequest getHttpOverrideForwardedRequest() { return httpOverrideForwardedRequest; } public HttpError getHttpError() { return httpError; } @JsonIgnore public Action getAction() { if (httpResponse != null) { return getHttpResponse(); } else if (httpResponseTemplate != null) { return getHttpResponseTemplate(); } else if (httpResponseClassCallback != null) { return getHttpResponseClassCallback(); } else if (httpResponseObjectCallback != null) { return getHttpResponseObjectCallback(); } else if (httpForward != null) { return getHttpForward(); } else if (httpForwardTemplate != null) { return getHttpForwardTemplate(); } else if (httpForwardClassCallback != null) { return getHttpForwardClassCallback(); } else if (httpForwardObjectCallback != null) { return getHttpForwardObjectCallback(); } else if (httpOverrideForwardedRequest != null) { return getHttpOverrideForwardedRequest(); } else if (httpError != null) { return getHttpError(); } else { return null; } } public Times getTimes() { return times; } public TimeToLive getTimeToLive() { return timeToLive; } public Expectation thenRespond(HttpResponse httpResponse) { if (httpResponse != null) { validationErrors("a response", httpResponse.getType()); this.httpResponse = httpResponse; this.hashCode = 0; } return this; } public Expectation thenRespond(HttpTemplate httpTemplate) { if (httpTemplate != null) { httpTemplate.withActionType(Action.Type.RESPONSE_TEMPLATE); validationErrors("a response template", httpTemplate.getType()); this.httpResponseTemplate = httpTemplate; this.hashCode = 0; } return this; } public Expectation thenRespond(HttpClassCallback httpClassCallback) { if (httpClassCallback != null) { httpClassCallback.withActionType(Action.Type.RESPONSE_CLASS_CALLBACK); validationErrors("a response class callback", httpClassCallback.getType()); this.httpResponseClassCallback = httpClassCallback; this.hashCode = 0; } return this; } public Expectation thenRespond(HttpObjectCallback httpObjectCallback) { if (httpObjectCallback != null) { httpObjectCallback.withActionType(Action.Type.RESPONSE_OBJECT_CALLBACK); validationErrors("a response object callback", httpObjectCallback.getType()); this.httpResponseObjectCallback = httpObjectCallback; this.hashCode = 0; } return this; } public Expectation thenForward(HttpForward httpForward) { if (httpForward != null) { validationErrors("a forward", httpForward.getType()); this.httpForward = httpForward; this.hashCode = 0; } return this; } public Expectation thenForward(HttpTemplate httpTemplate) { if (httpTemplate != null) { httpTemplate.withActionType(Action.Type.FORWARD_TEMPLATE); validationErrors("a forward template", httpTemplate.getType()); this.httpForwardTemplate = httpTemplate; this.hashCode = 0; } return this; } public Expectation thenForward(HttpClassCallback httpClassCallback) { if (httpClassCallback != null) { httpClassCallback.withActionType(Action.Type.FORWARD_CLASS_CALLBACK); validationErrors("a forward class callback", httpClassCallback.getType()); this.httpForwardClassCallback = httpClassCallback; this.hashCode = 0; } return this; } public Expectation thenForward(HttpObjectCallback httpObjectCallback) { if (httpObjectCallback != null) { httpObjectCallback .withActionType(Action.Type.FORWARD_OBJECT_CALLBACK); validationErrors("a forward object callback", httpObjectCallback.getType()); this.httpForwardObjectCallback = httpObjectCallback; this.hashCode = 0; } return this; } public Expectation thenForward(HttpOverrideForwardedRequest httpOverrideForwardedRequest) { if (httpOverrideForwardedRequest != null) { validationErrors("a forward replace", httpOverrideForwardedRequest.getType()); this.httpOverrideForwardedRequest = httpOverrideForwardedRequest; this.hashCode = 0; } return this; } public Expectation thenError(HttpError httpError) { if (httpError != null) { validationErrors("an error", httpError.getType()); this.httpError = httpError; this.hashCode = 0; } return this; } private void validationErrors(String actionDescription, Action.Type actionType) { if (actionType != Action.Type.RESPONSE && httpResponse != null) { throw new IllegalArgumentException("It is not possible to set " + actionDescription + " once a response has been set"); } if (actionType != Action.Type.RESPONSE_TEMPLATE && httpResponseTemplate != null) { throw new IllegalArgumentException("It is not possible to set " + actionDescription + " once a response template has been set"); } if (actionType != Action.Type.RESPONSE_CLASS_CALLBACK && httpResponseClassCallback != null) { throw new IllegalArgumentException("It is not possible to set " + actionDescription + " once a class callback has been set"); } if (actionType != Action.Type.RESPONSE_OBJECT_CALLBACK && httpResponseObjectCallback != null) { throw new IllegalArgumentException("It is not possible to set " + actionDescription + " once an object callback has been set"); } if (actionType != Action.Type.FORWARD && httpForward != null) { throw new IllegalArgumentException("It is not possible to set " + actionDescription + " once a forward has been set"); } if (actionType != Action.Type.FORWARD_TEMPLATE && httpForwardTemplate != null) { throw new IllegalArgumentException("It is not possible to set " + actionDescription + " once a forward template has been set"); } if (actionType != Action.Type.FORWARD_CLASS_CALLBACK && httpForwardClassCallback != null) { throw new IllegalArgumentException("It is not possible to set " + actionDescription + " once a class callback has been set"); } if (actionType != Action.Type.FORWARD_OBJECT_CALLBACK && httpForwardObjectCallback != null) { throw new IllegalArgumentException("It is not possible to set " + actionDescription + " once an object callback has been set"); } if (actionType != Action.Type.FORWARD_REPLACE && httpOverrideForwardedRequest != null) { throw new IllegalArgumentException("It is not possible to set " + actionDescription + " once a forward replace has been set"); } if (actionType != Action.Type.ERROR && httpError != null) { throw new IllegalArgumentException("It is not possible to set " + actionDescription + " callback once an error has been set"); } } @JsonIgnore public boolean isActive() { return hasRemainingMatches() && isStillAlive(); } private boolean hasRemainingMatches() { return times == null || times.greaterThenZero(); } private boolean isStillAlive() { return timeToLive == null || timeToLive.stillAlive(); } public boolean decrementRemainingMatches() { if (times != null) { return times.decrement(); } return false; } @SuppressWarnings("PointlessNullCheck") public boolean contains(HttpRequest httpRequest) { return httpRequest != null && this.httpRequest.equals(httpRequest); } @SuppressWarnings("MethodDoesntCallSuperMethod") public Expectation clone() { return new Expectation(httpRequest, times.clone(), timeToLive, priority) .withId(id) .withCreated(created) .thenRespond(httpResponse) .thenRespond(httpResponseTemplate) .thenRespond(httpResponseClassCallback) .thenRespond(httpResponseObjectCallback) .thenForward(httpForward) .thenForward(httpForwardTemplate) .thenForward(httpForwardClassCallback) .thenForward(httpForwardObjectCallback) .thenForward(httpOverrideForwardedRequest) .thenError(httpError); } @Override @JsonIgnore public String[] fieldsExcludedFromEqualsAndHashCode() { return excludedFields; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } if (hashCode() != o.hashCode()) { return false; } Expectation that = (Expectation) o; boolean equals = Objects.equals(httpResponse, that.httpResponse); boolean equals1 = Objects.equals(httpRequest, that.httpRequest); return Objects.equals(priority, that.priority) && equals1 && Objects.equals(times, that.times) && Objects.equals(timeToLive, that.timeToLive) && equals && Objects.equals(httpResponseTemplate, that.httpResponseTemplate) && Objects.equals(httpResponseClassCallback, that.httpResponseClassCallback) && Objects.equals(httpResponseObjectCallback, that.httpResponseObjectCallback) && Objects.equals(httpForward, that.httpForward) && Objects.equals(httpForwardTemplate, that.httpForwardTemplate) && Objects.equals(httpForwardClassCallback, that.httpForwardClassCallback) && Objects.equals(httpForwardObjectCallback, that.httpForwardObjectCallback) && Objects.equals(httpOverrideForwardedRequest, that.httpOverrideForwardedRequest) && Objects.equals(httpError, that.httpError); } @Override public int hashCode() { if (hashCode == 0) { hashCode = Objects.hash(priority, httpRequest, times, timeToLive, httpResponse, httpResponseTemplate, httpResponseClassCallback, httpResponseObjectCallback, httpForward, httpForwardTemplate, httpForwardClassCallback, httpForwardObjectCallback, httpOverrideForwardedRequest, httpError); } return hashCode; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy