Last active
February 28, 2024 17:20
-
-
Save ahmed-musallam/f6238afb3895a23d03b5a09899392108 to your computer and use it in GitHub Desktop.
A simple HTTP server jUnit 5 extension based on https://gist.github.com/rponte/710d65dc3beb28d97655
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ahmedmusallam.service; | |
import java.io.IOException; | |
import java.net.URI; | |
import org.apache.http.client.CredentialsProvider; | |
import org.apache.http.client.methods.CloseableHttpResponse; | |
import org.apache.http.client.methods.HttpGet; | |
import org.apache.http.impl.client.CloseableHttpClient; | |
import org.apache.http.impl.client.HttpClients; | |
import org.apache.http.util.EntityUtils; | |
public class HttpClientService { | |
/** Perform a get request with the provided credentials provider. */ | |
public String doGet(URI uri, CredentialsProvider credentialsProvider) throws IOException { | |
if (credentialsProvider == null || uri == null) { | |
return null; | |
} | |
try (CloseableHttpClient httpClient = | |
HttpClients.custom().setDefaultCredentialsProvider(credentialsProvider).build()) { | |
HttpGet httpGet = new HttpGet(uri); | |
try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) { | |
return EntityUtils.toString(httpResponse.getEntity()); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ahmedmusallam.service; | |
import static org.junit.jupiter.api.Assertions.*; | |
import com.ahmedmusallam.extension.HttpServerExtension; | |
import com.ahmedmusallam.extension.JsonSuccessHandler; | |
import java.io.IOException; | |
import java.net.URI; | |
import java.net.URISyntaxException; | |
import org.apache.http.client.CredentialsProvider; | |
import org.apache.http.client.utils.URIBuilder; | |
import org.apache.http.impl.client.BasicCredentialsProvider; | |
import org.junit.jupiter.api.Test; | |
import org.junit.jupiter.api.extension.ExtendWith; | |
import org.junit.jupiter.api.extension.RegisterExtension; | |
import org.mockito.Mock; | |
import org.mockito.junit.jupiter.MockitoExtension; | |
@ExtendWith(MockitoExtension.class) | |
class HttpClientServiceTest { | |
private HttpClientService httpClientService = new HttpClientService(); | |
@RegisterExtension // MUST be static, see: https://junit.org/junit5/docs/current/user-guide/#extensions-registration-programmatic-static-fields | |
static HttpServerExtension httpServerExtension = new HttpServerExtension(); | |
@Mock | |
CredentialsProvider credentialsProvider; | |
@Test | |
void doGet() throws IOException, URISyntaxException { | |
assertNull(httpClientService.doGet(null, credentialsProvider)); | |
assertNull(httpClientService.doGet(new URIBuilder().build(), null)); | |
httpServerExtension.registerHandler("/test", new JsonSuccessHandler("{}")); | |
URI uri = HttpServerExtension.getUriFor("/test"); | |
assertEquals("{}", httpClientService.doGet(uri, new BasicCredentialsProvider())); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ahmedmusallam.extension; | |
import com.sun.net.httpserver.HttpHandler; | |
import com.sun.net.httpserver.HttpServer; | |
import java.net.InetSocketAddress; | |
import java.net.URI; | |
import java.net.URISyntaxException; | |
import org.apache.http.client.utils.URIBuilder; | |
import org.junit.jupiter.api.extension.AfterAllCallback; | |
import org.junit.jupiter.api.extension.BeforeAllCallback; | |
import org.junit.jupiter.api.extension.ExtensionContext; | |
/* | |
* Note: I chose to implement `BeforeAllCallback` and AfterAllCallback | |
* but not `AfterEachCallback` and `BeforeEachCallback` for performance reasons. | |
* I wanted to only run one server per test class and I can register handlers | |
* on a per-test-method basis. You could implement the `BeforeEachCallback` and `AfterEachCallback` | |
* interfaces if you really need that behavior. | |
*/ | |
public class HttpServerExtension implements BeforeAllCallback, AfterAllCallback { | |
public static final int PORT = 6991; | |
public static final String HOST = "localhost"; | |
public static final String SCHEME = "http"; | |
private com.sun.net.httpserver.HttpServer server; | |
@Override | |
public void afterAll(ExtensionContext extensionContext) throws Exception { | |
if (server != null) { | |
server.stop(0); // doesn't wait all current exchange handlers complete | |
} | |
} | |
@Override | |
public void beforeAll(ExtensionContext extensionContext) throws Exception { | |
server = HttpServer.create(new InetSocketAddress(PORT), 0); | |
server.setExecutor(null); // creates a default executor | |
server.start(); | |
} | |
public static URI getUriFor(String path) throws URISyntaxException{ | |
return new URIBuilder() | |
.setScheme(SCHEME) | |
.setHost(HOST) | |
.setPort(PORT) | |
.setPath(path) | |
.build(); | |
} | |
public void registerHandler(String uriToHandle, HttpHandler httpHandler) { | |
server.createContext(uriToHandle, httpHandler); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.ahmedmusallam.extension; | |
import java.io.IOException; | |
import java.nio.charset.Charset; | |
import org.apache.commons.io.IOUtils; | |
import java.net.HttpURLConnection; | |
import com.sun.net.httpserver.HttpExchange; | |
import com.sun.net.httpserver.HttpHandler; | |
// credit: https://gist.github.com/rponte/710d65dc3beb28d97655#file-httpserverrule-java | |
public class JsonSuccessHandler implements HttpHandler { | |
private String responseBody; | |
private static final String contentType = "application/json"; | |
public JsonSuccessHandler() {} | |
public JsonSuccessHandler(String responseBody) { | |
this.responseBody = responseBody; | |
} | |
@Override | |
public void handle(HttpExchange exchange) throws IOException { | |
exchange.getResponseHeaders().add("Content-Type", contentType); | |
exchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, responseBody.length()); | |
IOUtils.write(responseBody, exchange.getResponseBody(), Charset.defaultCharset()); | |
exchange.close(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment