...
The CPS-RI module which is responsible for data persistence and retrieval from the database is based on
Spring on Spring Data framework.
Following components are used:
...
In order to reach the desirable level of reliability it's expected the functionality to be covered with tests.
Below is comparison between unit test vs integration test approaches.
draw.io Diagram | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
...
draw.io Diagram | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
- Docker provides a container with running database instance which is used during the test
- Test container component communicates with Docker via CLI (or Engine API depending on Docker deployment),
manages required container to be created/started before test and stopped/removed after the test is completed - Test container component is used by JUnit test as a Class Rule
- The connection to test database is served using standard Spring framework components
...
Running instance of database for integration test is provided by Test TestContainers Java library component.
...
draw.io Diagram | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
NB. The default remaining test containers removal (on JVM termination) was served by dedicated RYUK container (part of TestContainers library).
However this container requires running as privileged one, so it was disabled in order make TestContainers available on Jenkins. It made it
necessary to explicitly invoke test container removal logic on JVM termination event.
@SpringBootTest
Using @SpringBootTest
annotation for tests allows @Autowired
Spring components (including JPA repository instances) initialization for testing
same way as it's done on regular Spring Boot application execution.
To be used the @SpringBootApplication
annotated class is required. However both application class and associated configuration are allocated
in CPS-REST maven module which cannot be accessed from CPS-RI module on build (when the tests classes are compiled and executed).
So in order to fulfill the @SpringBootTest requirements and to properly initialize DataSource object the substitutions for both Spring Boot application
class and configuration (DataSource properties) are set directly within CPS-RI module (test scope).
draw.io Diagram | ||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
NB. There is no need to initialize the Spring Boot application within CPS-RI in same scale as it's done for CPS-REST module, so the
application.yaml configuration within CPS-RI module contains mainly database related parameters. In case these parameters are updated
within primary configuration file same changes require to be provided to test configuration file as well.
Database
...
initialization
The datasource is configured in application.yml test configuration file like below
Code Block | ||
---|---|---|
| ||
spring:
datasource:
url: ${DB_URL}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
driverClassName: org.postgresql.Driver
initialization-mode: always |
The database connection parameters are expected to be defined using environment variables.
Due to ports exposed for a test containers (part of DB_URL) are variable (to allow concurrent tests executions and to avoid conflicts with
existing containers) the expected variables are set after the test container being initialized directly from TestContainer wrapper artifact
Code Block | ||||
---|---|---|---|---|
| ||||
@Override
public void start() {
super.start();
System.setProperty("DB_URL", databaseTestContainer.getJdbcUrl());
System.setProperty("DB_USERNAME", databaseTestContainer.getUsername());
System.setProperty("DB_PASSWORD", databaseTestContainer.getPassword());
} |
The database schema initialization is performed by Spring framework (same way for both runtime and testing) using schema.sql file.
See https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-database-initialization
Test data
Spring framework allows data setting for testing using @Sql
annotation.
Single or multiple SQL scripts can be defined to be executed before the test method (resources folder is a root).
Code Block | ||
---|---|---|
| ||
@Test
@Sql({"/data/clear.sql", "/data/test-data.sql"})
public void test() {
// test
} |
Test class template
Below is an example of test class (setup ) which can be used as a template for new database tests being added to CPS project.
Code Block | ||
---|---|---|
| ||
package org.onap.cps.spi.impl;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.onap.cps.DatabaseTestContainer;
import org.onap.cps.spi.CpsAdminPersistenceService;
import org.onap.cps.spi.repository.DataspaceRepository;
import org.onap.cps.spi.repository.SchemaSetRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest
public class CpsAdminPersistenceServiceTest {
private static final String CLEAR_DATA = "/data/clear-all.sql";
private static final String SET_DATA = "/data/anchor.sql";
@ClassRule
public static DatabaseTestContainer databaseTestContainer = DatabaseTestContainer.getInstance();
@Autowired
private CpsAdminPersistenceService cpsAdminPersistenceService;
@Autowired
private DataspaceRepository dataspaceRepository;
@Autowired
private SchemaSetRepository schemaSetRepository;
@Test
@Sql({CLEAR_DATA, SET_DATA})
public void testCreateAnchor() {
// test ...
}
}
|
@SpringBootTest
...
Resources
Frameworks and libraries:
- https://www.testcontainers.org/
- https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html
- https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html#integration-testing-annotations-spring
- https://docs.spring.io/spring-boot/docs/current/reference/html/howto.html#howto-database-initialization
Tutorials:
- https://reflectoring.io/spring-boot-data-jpa-test/
- https://reflectoring.io/spring-boot-test/
- https://www.baeldung.com/docker-test-containers
- https://www.baeldung.com/spring-boot-testcontainers-integration-test
...