001/* 002 * Copyright 2022-2025 Revetware LLC. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package com.soklet; 018 019import javax.annotation.Nonnull; 020import java.util.function.Consumer; 021 022/** 023 * Simulates server behavior of accepting a request and returning a response, useful for writing integration tests. 024 * <p> 025 * <a href="https://www.soklet.com/docs/server-sent-events">Server-Sent Event</a> simulation is also supported. 026 * <p> 027 * Instances of {@link Simulator} are made available via {@link com.soklet.Soklet#runSimulator(SokletConfig, Consumer)}. 028 * <p> 029 * Usage example: 030 * <pre>{@code @Test 031 * public void basicIntegrationTest() { 032 * // Build your configuration however you like 033 * SokletConfig config = obtainMySokletConfig(); 034 * 035 * // Instead of running on a real HTTP server that listens on a port, 036 * // a simulator is provided against which you can issue requests 037 * // and receive responses. 038 * Soklet.runSimulator(config, (simulator -> { 039 * // Construct a request. 040 * // You may alternatively specify query parameters directly in the URI 041 * // as a query string, e.g. "/hello?name=Mark" 042 * Request request = Request.with(HttpMethod.GET, "/hello") 043 * .queryParameters(Map.of("name", Set.of("Mark"))) 044 * .build(); 045 * 046 * // Perform the request and get a handle to the result 047 * RequestResult result = simulator.performRequest(request); 048 * 049 * // Verify status code 050 * Integer expectedCode = 200; 051 * Integer actualCode = result.getMarshaledResponse().getStatusCode(); 052 * Assert.assertEquals("Bad status code", expectedCode, actualCode); 053 * })); 054 * }}</pre> 055 * <p> 056 * Full documentation is available at <a href="https://www.soklet.com/docs/automated-testing">https://www.soklet.com/docs/automated-testing</a>. 057 * 058 * @author <a href="https://www.revetkn.com">Mark Allen</a> 059 */ 060public interface Simulator { 061 /** 062 * Given a request, process it and return response data (both logical {@link Response}, if present, and the {@link MarshaledResponse} bytes to be sent over the wire) as well as the matching <em>Resource Method</em>, if available. 063 * 064 * @param request the request to process 065 * @return the result (logical response, marshaled response, etc.) that corresponds to the request 066 */ 067 @Nonnull 068 RequestResult performRequest(@Nonnull Request request); 069 070 /** 071 * Registers a {@link ServerSentEvent} "consumer" for the given {@link ResourcePath} - similar to how a real client would listen for Server-Sent Events. 072 * <p> 073 * See documentation at <a href="https://www.soklet.com/docs/server-sent-events#testing">https://www.soklet.com/docs/server-sent-events#testing</a>. 074 * 075 * @param resourcePath the Resource Path on which to listen for Server-Sent Events 076 * @param serverSentEventConsumer function to be invoked when a Server-Sent Event has been broadcast on the Resource Path 077 */ 078 void registerServerSentEventConsumer(@Nonnull ResourcePath resourcePath, 079 @Nonnull Consumer<ServerSentEvent> serverSentEventConsumer); 080 081 /** 082 * Acquires a Server-Sent Event broadcaster for the given {@link ResourcePath}. 083 * <p> 084 * See documentation at <a href="https://www.soklet.com/docs/server-sent-events#testing">https://www.soklet.com/docs/server-sent-events#testing</a>. 085 * 086 * @param resourcePath the Resource Path on which to broadcast Server-Sent Events 087 * @return a Server-Sent Event broadcaster 088 */ 089 @Nonnull 090 ServerSentEventBroadcaster acquireServerSentEventBroadcaster(@Nonnull ResourcePath resourcePath); 091}