I recently ran into a situation where a web service client had issues when invoking a webservice via HTTPS. To reproduce, I needed a lightweight, JUnit-based test to reproduce the problem and write a regression test. Here is how I got it to work:

First, I used the basic HTTP test setup. Now however, I needed Jetty to provide a HTTPS connector. For this to work, Jetty – just like any other webserver, such as apache – needs a server certificate and a private key in a keystore. To create the keystore, I simply followed the excellent Jetty SSL guide. Namingly, I did this (using Ubuntu, see the above link for alternatives):

openssl genrsa -des3 -out jetty.key
openssl req -new -x509 -key jetty.key -out jetty.crt
openssl pkcs12 -inkey jetty.key -in jetty.crt -export -out jetty.pkcs12
$JAVA_HOME/bin/keytool -importkeystore -srckeystore jetty.pkcs12 -srcstoretype PKCS12 -destkeystore keystore

Once I had the keystore set up, I placed it in the src/main/resources folder (the root of the classpath, in case you’re not a maven user) and extended the HttpTestServer like so:

import java.net.URL;

import org.junit.Ignore;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.security.SslSocketConnector;

/**
 * A test server for testing SSL requests.
 * 
 * @author Olaf Otto
 */
@Ignore
public class SslTestServer extends HttpTestServer {
	private static final int HTTPS_PORT = 50443;

	public SslTestServer() {
	}

	public SslTestServer(String mockData) {
		super(mockData);
	}

	@Override
	protected void configureServer() {
		super.configureServer();
		Connector secureConnector = createSecureConnector();
		getServer().addConnector(secureConnector);
	}

	private Connector createSecureConnector() {
		SslSocketConnector connector = new SslSocketConnector();
		connector.setPort(HTTPS_PORT);
		URL keystoreUrl = getClass().getClassLoader().getResource("keystore");
		connector.setKeystore(keystoreUrl.getFile());
		connector.setKeyPassword("test");
		return connector;
	}

	public static void main(String[] args) {
		SslTestServer server = new SslTestServer();
		try {
			server.start();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
}

(I added the @Ignore annotation as I placed the class in the test sources folder, though it’s not a test…)
You might use it in your JUnit-based test like so:

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * @author Olaf Otto
 */
public class MySslTest {
	private SslTestServer _server;

	@Before
	public void startServer() throws Exception {
		_server = new SslTestServer();
		_server.start();
	}

	@After
	public void stopServer() throws Exception {
		_server.stop();
	}

	@Test
	public void mySsltest() {
		_server.setMockResponseData("<xml>My client expects this response</xml>");
		// Perform tests on port 50443...
	}
}

Here is the whole package as a maven 2 project (including the keystore with a self-signed certificate). Download, unzip, and give it a try (mvn test).

Tagged with →  
Share →

One Response to Testing SSL (HTTPS) clients with Junit and Jetty

  1. Josh says:

    To avoid SSL errors when using a self-signed/untrusted certificate you can add the following to the test class:

    @Before
    public void setUp() {
    URL keystoreUrl = getClass().getClassLoader().getResource(“keystore”);
    System.setProperty(“javax.net.ssl.trustStore”, keystoreUrl.getFile());
    System.setProperty(“javax.net.ssl.trustStorePassword”, “test”);
    }
    This will make the server use your test keystore instead of the built in keystore so the test certificate will be trusted.

    Also make sure that the common name in the certificate you create matches the host of your test server i.e. “localhost”.

Leave a Reply

Your email address will not be published. Required fields are marked *