-
Notifications
You must be signed in to change notification settings - Fork 28
4. Services
The objective of services is to act as representative between the scenario and the internal managed resource:
@QuarkusApplication
static final DefaultService pingApp = new DefaultService();
This service will host the quarkus application internally, but it will also expose the functionality to interact with it:
-
withProperty
: Intuitive usage of properties. -
Service Lifecycle
The framework allows to add actions via hooks in every stage of the service lifecycle:
@QuarkusApplication
static final DefaultService pingApp = new DefaultService()
.onPreStart(GreetingResourceTest::onPreStart);
.onPostStart(GreetingResourceTest::onPostStart);
- Services are startable and stoppable by default
Any Quarkus application and containers can be stopped to cover more complex scenarios. The test framework will restart the services by you before starting a new test case.
- Services are logabble
We can verify any traces that the managed resources is logging.
@QuarkusScenario
public class DevModeMySqlDatabaseIT {
@DevModeQuarkusApplication
static DefaultService app = new DefaultService();
@Test
public void verifyLogsToAssertDevMode() {
app.logs().assertContains("Profile dev activated. Live Coding activated");
}
}
We can add custom implementations of services to share common functionality. The test framework provides the following services:
There is a custom service implementation where we can use REST assured:
@QuarkusScenario
public class PingPongResourceIT {
@QuarkusApplication
static final RestService pingApp = new RestService();
@Test
public void shouldPingWorks() {
pingApp.given().get("/ping").then().statusCode(HttpStatus.SC_OK).body(is("ping"));
}
}
The test framework have some utilities to ease the setup of database containers. In order to use these services, you need to add the following dependency into your Maven configuration:
<dependency>
<groupId>io.quarkus.qe</groupId>
<artifactId>quarkus-test-service-database</artifactId>
<scope>test</scope>
</dependency>
The supported database services are:
- MySQL service
- MariaDB service
- DB2 service
- SQL Server service (we can't set a custom user, password and database)
- PostgreSQL service
- Oracle service
- MongoDB service
All the database services contain the following methods:
-
getJdbcUrl
: to return the JDBC connection URL. -
getReactiveUrl
: to return the reactive way connection URL.
Example usage:
@QuarkusScenario
public class MySqlDatabaseIT {
@Container(image = "mysql/mysql-server:8.0", port = MYSQL_PORT, expectedLog = "port: 3306 MySQL Community Server")
static MySqlService database = new MySqlService();
@QuarkusApplication
static RestService app = new RestService()
.withProperty("quarkus.datasource.username", database.getUser())
.withProperty("quarkus.datasource.password", database.getPassword())
.withProperty("quarkus.datasource.jdbc.url", database::getJdbcUrl)
.withProperty("quarkus.datasource.reactive.url", database::getReactiveUrl);
// ...
}
MySQL example in here.
The test framework have some utilities to ease the setup of infinispan containers. In order to use this service, you need to add the following dependency into your Maven configuration:
<dependency>
<groupId>io.quarkus.qe</groupId>
<artifactId>quarkus-test-service-infinispan</artifactId>
<scope>test</scope>
</dependency>
Example usage:
@QuarkusScenario
public class BasicInfinispanBookCacheIT extends BaseBookCacheIT {
@Container(image = "infinispan/server:12.1", expectedLog = "Infinispan Server.*started in", port = 11222)
static final InfinispanService infinispan = new InfinispanService();
@QuarkusApplication
static final RestService app = new RestService()
.withProperty("quarkus.infinispan-client.server-list", infinispan::getInfinispanServerAddress)
.withProperty("quarkus.infinispan-client.auth-username", infinispan.getUsername())
.withProperty("quarkus.infinispan-client.auth-password", infinispan.getPassword());
}
For more advanced setup, we can add custom configuration as for example to enable JKS support:
@QuarkusScenario
public class UsingJksInfinispanBookCacheIT extends BaseBookCacheIT {
@Container(image = "infinispan/server:12.1", expectedLog = "Infinispan Server.*started in", port = 11222)
static final InfinispanService infinispan = new InfinispanService()
.withConfigFile("jks-config.yaml")
.withSecretFiles("jks/server.jks");
@QuarkusApplication
static final RestService app = new RestService()
.withProperty("quarkus.infinispan-client.server-list", infinispan::getInfinispanServerAddress)
.withProperty("quarkus.infinispan-client.auth-username", infinispan.getUsername())
.withProperty("quarkus.infinispan-client.auth-password", infinispan.getPassword())
.withProperty("quarkus.infinispan-client.trust-store", "secret::/jks/server.jks")
.withProperty("quarkus.infinispan-client.trust-store-password", "changeit")
.withProperty("quarkus.infinispan-client.trust-store-type", "jks");
}
For OpenShift/Kubernetes deployments and depending on the used Infinispan images, it might not be possible to communicate with the Infinispan service using the exposed routes, so we need to configure our scenario to use the internal services instead:
ts.infinispan.openshift.use-internal-service-as-url=true
ts.infinispan.kubernetes.use-internal-service-as-url=true
Full example in here.
Maven dependency:
<dependency>
<groupId>io.quarkus.qe</groupId>
<artifactId>quarkus-test-service-consul</artifactId>
<scope>test</scope>
</dependency>
Example usage:
@QuarkusScenario
public class GreetingResourceIT {
@Container(image = "${property.do.not.exist:quay.io/bitnami/consul:1.9.3}", expectedLog = "Synced node info", port = 8500)
static ConsulService consul = new ConsulService();
// ...
}
Full example in here.
We can enable the gRPC feature to test Quarkus application using the @QuarkusApplication(grpc = true)
annotation. This way we can verify purely gRPC applications using the GrpcService
service wrapper:
@QuarkusScenario
public class GrpcServiceIT {
static final String NAME = "Victor";
@QuarkusApplication(grpc = true) // enable gRPC support
static final GrpcService app = new GrpcService();
@Test
public void shouldHelloWorldServiceWork() {
HelloRequest request = HelloRequest.newBuilder().setName(NAME).build();
HelloReply response = GreeterGrpc.newBlockingStub(app.grpcChannel()).sayHello(request);
assertEquals("Hello " + NAME, response.getMessage());
}
}
In the same way, we can add default services to ease and share common functionality. As part of the test framework, we added the consul service as an example.
public class YourCustomService extends BaseService<ConsulService> {
// your new methods
}
And use it:
@QuarkusScenario
public class GreetingResourceIT {
@Container // ... or @QuarkusApplication
static final YourCustomService app = new YourCustomService();
// your methods will be available
}