In the following post, I wanna share with you a simple solution that will cover all your needs in the process of testing a microservice on the component level or in an isolated environment, where you as a tester will have access only to the API level.
Used tech stack
We will use the following technologies in our little project:
- java 8
- maven
- rest-assured
- cucumber with JUnit 5
- testing application (https://jsonplaceholder.typicode.com)
Adding all dependencies
Start adding all necessary dependencies and the first one will be rest-assured, those who are not familiar with rest-assured can find more information here.
In the pom.xml file we will add the following:
<!-- Start REST-assured dependencies --> <dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <version>${resassured.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>${jackson-databind.version}</version> </dependency> <!-- End REST-assured dependencies -->
After that let’s add the cucumber 7 dependencies and JUnit 5 :
<!-- Start Cucumber dependencies --> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-java</artifactId> <version>${cucumber.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-junit-platform-engine</artifactId> <version>${cucumber.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.platform</groupId> <artifactId>junit-platform-suite</artifactId> <version>${junit-platform.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>io.cucumber</groupId> <artifactId>cucumber-spring</artifactId> <version>${cucumber.version}</version> <scope>test</scope> </dependency> <!-- End Cucumber dependencies -->
Add spring boot starter test dependency for bean declaration and configuration with Lombok for fast code writing.
<!-- End Cucumber dependencies --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <version>${spring-boot-starter.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> </dependency>
Cucumber 7 and JUnit 5 configurations
In order to make cucumber be started by Junit 5 after adding the dependencies is required to declare the necessary configuration, the runner, and the configuration class that contains necessary annotations.
There are multiple approaches, at the same time in order to make your testing framework adaptable better to have separate configuration classes for test application context and for cucumber integration with JUnit5, that’s why we created the following classes: CucumberSpringTestConfig – represent the test application context configurations.
@Configuration @PropertySource("classpath:application.properties") public class CucumberSpringTestConfig { @Bean public ScenarioContext scenarioContext() { return new ScenarioContext(); } @Bean public UserSearchAction userSearchAction() { return new UserSearchActionImpl(); } @Bean public UserPostAction userPostAction() { return new UserPostActionImpl(); } @Bean public FieldsValidator fieldsValidator() { return new FieldsValidatorImpl(); } }
@CucumberContextConfiguration @ContextConfiguration(classes = {CucumberSpringTestConfig.class}, loader = AnnotationConfigContextLoader.class) public class TestGeneralHook { @Value("${test.application.base.uri:https://jsonplaceholder.typicode.com/}") private String testApplicationBaseURI; @AfterAll public static void resetRestAssuredConfiguration() { RestAssured.reset(); } @Before public void setUpApplicationTestBaseURI() { RestAssured.baseURI = testApplicationBaseURI; } }
TestGeneralHook – representing the general test hook where @CucumberContextConfiguration annotation is added in order to specify for JUnit the configuration class and @ContextConfiguration(classes = {CucumberSpringTestConfig.class} is pointing to our previous configuration test application context.
And that’s it now we have all tools configured together and we can start to define our test steps and implementation for them.
I’m opting for code that is consistently structured, and easy to read, broken down into specific related packages and class levels, promoting maintainability and enhancing the overall testing experience. That’s why I’m using the Single Responsibility pattern and creating separate interfaces and actions for specific domains.
You can analyze the whole project that it’s available on Git Hub.