Embedded Java HTTPS server for integration testing

2.5k views Asked by At

I'm writing integration tests for a Mule ESB application which connects to an external API via HTTPS. I'd like to mock the external API and run an end-to-end integration test during the Maven build. My question is about setting up an embedded HTTPS server. I've tried to use Jersey, but it only provides HTTP. I was looking at this example

https://github.com/jersey/jersey/tree/master/examples/https-clientserver-grizzly

and I was wondering if there is still some manual step involved, or if it works automatically setting everything up every time the build is kicked off.

Any suggestions or ideas?

Edit. My final goal is to deploy a JAX-RS service in an embedded server which is accessible via HTTPS. And that needs no client-side keys/certificate configuration.

Edit 2. Now my problem concerns certificates. The point of integration tests is to mock external components and verify that my application works. Now, if I set up an embedded HTTPS server and use a cmd-line built certificate, I need to add SSL configuration in the client (as @Ryan Hoegg pointed out). This is not what I would ideally want: Is there a solution to get it working without having to modify my client application code? This should be a general Java question that goes beyond Mule.

4

There are 4 answers

5
Ryan Hoegg On BEST ANSWER

I use confluex-mock-http for this. Under the hood it uses Jetty, but it does all the configuration for you. Creating the MockHttpsServer immediately starts the HTTPS server:

public static final int PORT = 1443;
private MockHttpsServer mockServer;

@Before
public void initHttps() {
    mockServer = new MockHttpsServer(PORT);
    mockServer.respondTo(get("a-service/resource")).withBody(expectedResponse);
}

You can set up your Mule application to trust the certificate used by the mock server. A JKS formatted truststore is available on the classpath, and you can provide it to your HTTPS connector like so:

<https:connector name="someHttpsConnector">
    <https:tls-server path="confluex-mock.truststore" storePassword="confluex" />
</https:connector>

I think some older versions of mule have trouble with this approach, because I needed to use the workaround here.

EDIT: You can include this configuration for the HTTPS Connector only when tests are running by using a Spring profile:

<spring:beans profile="test">
    <mule>
        <!-- connector configuration goes here -->
    </mule>
</spring:beans>

One way to make sure the profile is indeed active when the tests run is to simply set it in a @BeforeClass method:

@BeforeClass
public void initEnvironment() {
    System.setProperty("spring.profiles.active", "test");
}
6
dasrohith On

If you are willing to embed any other server, try Jetty.

For configuration see this question

0
alexey On

The example you refer works automatically. The only manual part I can think about it's security stores (keystore, truststore) creation. Once you have them you can feed Grizzly HttpServer same way it's done in the example.

4
Petter Nordlander On

Why don't you simply use Mule for this task?

Create an additional Mule XML file which exposes the JAX-RS service over HTTPS. The idea is to not include this in the production code (i.e. refer it from mule-context.xml), but rather load it from the test case.

You can submit it as a configuration side-by-side with the production config in the FunctionalTestCase class.

Your mock service could look a bit like this (excluding the JAX-RS annotated bean that provides the actual implementation of course).

<flow name="mock-service">
    <https:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8085" path="mockapi"/>
    <jersey:resources>
        <component>
            <spring-object bean="mockApiBean"/>
        </component>
    </jersey:resources>
</flow>