Configure JettyTestContainer com SSL para JerseyTest
Recebi a tarefa de configurar testes de integração para o código da minha equipe. Esses testes exigirão a execução de solicitações HTTPS para endpoints REST implementados em Jersey 2.27. Em minha pesquisa sobre como realizar esse tipo de teste, me deparei com este artigo de Baeldung que me indicou o Jersey Test Framework e os containers de provedor que eles implementaram para esse propósito. Escolhi o container Jetty, pois nosso código estava usando uma instância Jetty 'roll your own' para fazer tudo isso. Comecei a implementação de nossos testes e encontrei dificuldades para configurar SSL para o JettyTestContainer que atenderia às solicitações restantes. Comecei a receber uma IllegalArgumentException declarando que "O esquema de URI deve ser http quando não estiver usando SSL." Não sei como proceder.
Esta é minha aula de teste:
public class ProjectTest extends JerseyTest {
private SSLContext sslCtx;
@Override
protected Application configure() {
ResourceConfig conf = new ResourceConfig(Sets.newHashSet(RestSuite1.class));
SslConfigurator sslConfig = SslConfigurator.newInstance()
.trustStoreFile()
.trustStorePassword()
.keyStoreFile()
.keyStorePassword()
sslCtx = sslConfig.createSSLContext();
}
@Override
public URI getBaseUri() {
return URI.create("https://localhost:1234")
}
@Override
public Client getClient() {
return ClientBuilder.newBuilder().sslContext(sslCtx).build();
}
@Test
public void test1() throws Exception {
String testString = "HelloWorld";
OurObject oo = target("/restSuite1")
.request()
.post(Entity.entity(testString, MediaType.APPLICATION_JSON), String.class);
}
}
Aqui está um RestSuite1:
@Path("restSuite1")
@Produces("application/json")
public class RestSuite1 {
@POST
@Consumes("application/json")
@Produces("application/json")
public String doSomething(String payload) {
// Do Something
}
}
Aqui está meu pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>my-application1</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>my war</name>
<url>http://some-url.com</url>
<dependencies>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.27</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>2.27</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-jetty</artifactId>
<version>2.27</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Devo observar que, antes de tentar a configuração SSL, consegui alcançar o ponto de extremidade POST / restSuite1 com êxito.
Eu encontrei essa pergunta , mas não parece uma configuração SSL do Grizzly que seria usada em um cenário de JerseyTest.
Eu encontrei esta pergunta , mas parece que está definindo funções de usuário e não uma configuração SSL real.
Então eu encontrei essa pergunta , e a pessoa que a fez parece ter o mesmo problema que eu, porém ninguém nunca respondeu à pergunta.
Por favor ajude!
Respostas
Parece que essa opção não está disponível no JerseyTest. Criei uma solicitação pull para adicionar esta opção. Por favor, dê uma olhada aqui:https://github.com/eclipse-ee4j/jersey/pull/4573 Não tenho certeza de quão rápido eles irão aprovar e publicar ...
Eu sei que não era a resposta que você está procurando ... No entanto, se você ainda deseja configurar seu servidor com ssl e testar sua aplicação com https sem esperar até que a solicitação de pull seja aprovada, você pode dar uma olhada no meu projeto github que tem um exemplo básico de teste de um servidor jersey com grizzly sem JerseyTest: Application & IntegrationTest
=============== ATUALIZAÇÃO # 1 20-12-2020 ===============
A solicitação pull foi aprovada, mesclada e liberada. Ele agora está disponível a partir da versão 2.33. Agora é possível fornecer um sslcontext com sslparameters para configurar seu teste de camisa. Um exemplo de configuração seria:
public class SecuredJerseyTest extends JerseyTest {
@Override
protected TestContainerFactory getTestContainerFactory() {
return new GrizzlyTestContainerFactory();
}
@Path("hello")
public static class TestResource {
@GET
public String hello() {
return "hello";
}
}
@Override
protected Application configure() {
return new ResourceConfig(TestResource.class);
}
@Override
protected URI getBaseUri() {
return UriBuilder
.fromUri("https://localhost")
.port(getPort())
.build();
}
@Override
protected Optional<SSLContext> getSslContext() {
SSLContext sslContext = ... // your initialised server sslContext
return Optional.of(sslContext);
}
@Override
protected Optional<SSLParameters> getSslParameters() {
serverSslParameters = new SSLParameters();
serverSslParameters.setNeedClientAuth(false);
return Optional.of(serverSslParameters);
}
@Test
public void testHello() {
SSLContext sslContext = ... // your initialised client sslContext
Client client = ClientBuilder.newBuilder()
.sslContext(sslContext)
.build();
WebTarget target = client.target(getBaseUri()).path("hello");
String s = target.request().get(String.class);
Assert.assertEquals("hello", s);
}
}