I am trying to generate jacoco code coverage report for my restassured testcases pointing to the rest end points. I am using springboot application. My controller class looks like :
@RestController
public class ChallengeController {
private static final Logger LOGGER = LoggerFactory.getLogger(ChallengeController.class);
@Autowired
private ChallengeService challengeService;
public ChallengeController(ChallengeService challengeService) {
this.challengeService = challengeService;
}
@GetMapping(path = "/hello",
produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String hello() {
return "hello";
}
@GetMapping(path = "/hello/greeting/{name}",
produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String greeting(@PathVariable(value = "name") String name) {
return challengeService.greeting(name);
}
}
My service class looks like
@Service
@Component
public class ChallengeService {
private static final Logger LOGGER = LoggerFactory.getLogger(ChallengeService.class);
public ChallengeService() {
}
public String greeting(String name) {
return "hello " + name;
}
}
My POM looks like
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<argLine>${surefireArgLine}</argLine>
<excludes>
<exclude>**/ResilienceTests.java</exclude>
<exclude>**/CucumberTest.java</exclude>
<exclude>**/DummyChallengeTest.java</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco-maven-plugin.version}</version>
<executions>
<execution>
<id>pre-unit-test</id>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</destFile>
<propertyName>surefireArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-unit-test</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/coverage-reports/jacoco-ut.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-ut</outputDirectory>
</configuration>
</execution>
<execution>
<id>pre-integration-test</id>
<phase>validate</phase>
<goals>
<goal>prepare-agent-integration</goal>
</goals>
<configuration>
<destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
<propertyName>failsafeArgLine</propertyName>
</configuration>
</execution>
<execution>
<id>post-integration-test</id>
<phase>post-integration-test</phase>
<goals>
<goal>report-integration</goal>
</goals>
<configuration>
<!-- excluding everything except controller class -->
<excludes>
<exclude>**/common/*.class</exclude>
<exclude>**/config/*.class</exclude>
<exclude>**/domain/*.class</exclude>
<exclude>**/exception/*.class</exclude>
<exclude>**/mapper/*.class</exclude>
<exclude>**/service/*.class</exclude>
<exclude>**/simulator/Main.class</exclude>
</excludes>
<dataFile>${project.build.directory}/coverage-reports/jacoco-it.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-it</outputDirectory>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
<classFilesDIrectory>${project.build.directory}/classes</classFilesDIrectory>
</configuration>
</execution>
<!-- merging jacoco reports-->
<execution>
<id>report-aggregate</id>
<phase>verify</phase>
<goals>
<goal>report-aggregate</goal>
</goals>
</execution>
<execution>
<id>merge-results</id>
<phase>verify</phase>
<goals>
<goal>merge</goal>
</goals>
<configuration>
<fileSets>
<fileSet>
<directory>${project.build.directory}/coverage-reports/</directory>
<includes>
<include>*.exec</include>
</includes>
</fileSet>
</fileSets>
<destFile>${project.build.directory}/coverage-reports/aggregate.exec</destFile>
</configuration>
</execution>
<execution>
<id>post-merge-report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${project.build.directory}/coverage-reports/aggregate.exec</dataFile>
<outputDirectory>${project.reporting.outputDirectory}/jacoco-aggregate</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<executions>
<execution>
<id>integration-tests</id>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<argLine>${failsafeArgLine}</argLine>
<includes>
<include>**/*CucumberTest.java</include>
<include>**/*DummyChallengeTest.java</include>
</includes>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
<!-- When running as a Maven plugin, the JaCoCo agent configuration is prepared by invoking the prepare-agent
or prepare-agent-integration goals, before the actual tests are run. This sets a property named argLine which
points to the JaCoCo agent, later passed as a JVM argument to the test runner -->
</configuration>
</execution>
</executions>
</plugin>
My test class looks like
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DummyChallengeTest extends AbstractSteps {
@Test
public void testHelloEndpoint() {
RestAssured.baseURI = "http://localhost:8082";
RestAssured.basePath ="/hello";
Response res = given()
.when().get()
.then().log().all()
.extract().response();
Assert.assertEquals("hello", res.getBody().asString());
}
@Test
public void testGreetingEndpoint() {
String uuid = UUID.randomUUID().toString();
//getServiceUrl() returning me the application base url
String requestUrl = getServiceUrl() + "/hello/greeting/{name}";
given()
.pathParam("name", uuid)
.when().get(requestUrl)
.then().log().all()
.statusCode(200)
.body(is("hello " + uuid)).log().all().extract();
}
}
Inside target/site/jacoco-it/jacoco-sessions.html I can locate my controller and service java files.
I am getting partial coverage on my controller file only these line
@Autowired
private ChallengeService challengeService;
public ChallengeController(ChallengeService challengeService) {
this.challengeService = challengeService;
}
However I am not getting any coverage on the end points, specifically on these lines
@GetMapping(path = "/hello",
produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String hello() {
return "hello";
}
@GetMapping(path = "/hello/greeting/{name}",
produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String greeting(@PathVariable(value = "name") String name) {
return challengeService.greeting(name);
}
Note : 1. My restassured testcases runs fine and all are passing. 2. When I am using Quarkus application, and Quarkus Test, then this same jacoco implementation giving me full coverage for end points. 3. I am getting full coverage for my Unit testcases.
When I am using Quarkus application, and Quarkus Test, then this same jacoco implementation giving me full coverage for end points.
I have seen some people are saying to run your application and test from same jvm. I am not sure how to do this correctly. Also if this solution is possible to implement in jenkins pipeline.
I have not tried Arquillian yet.