Spring Boot - All tests in a folder are excluded from coverage report - spring-boot

people.
I have this Spring Boot application with some services, utilities and controllers to test.
I have written tests for all of them, 35 so far, and the 35 tests get executed correctly.
The problem is that, for some reason, when I generate code coverage reports, the classes from the service directory appear with 0 coverage, even when their corresponding tests were executed without errors, as you can see in the image below.
For instance, the Dummy and DummyTest classes are a copy from other two classes in a different package -util instead of service- and those from utils have no problem. The curse takes place only inside of service.
As an example, these are the contents of Dummy and DummyTest.
I have rewritten it without mocks, but it does not work either way:
package quality.service;
import org.springframework.stereotype.Component;
import java.util.Base64;
#Component
public final class Dummy {
private Dummy() {
}
public static String encodeStringBase64(String string) {
return Base64.getEncoder().encodeToString(string.getBytes());
}
}
//---------------------------------------------------------
package quality.service;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static quality.service.Dummy.encodeStringBase64;
public class DummyTest {
#Test
public void testEncodeStringBase64ReturnsEmptyValue() {
assertEquals("", encodeStringBase64(""));
}
#Test
public void testEncodeStringBase64ReturnsEncodedString() {
assertEquals("VGVzdFN0cmluZ0AwMjQ1", encodeStringBase64("TestString#0245"));
}
}
Any suggestion would be really appreciated.
Screenshot

Related

How do I annotate my JUnit test so it will run the way my Spring Boot app runs?

I have a Spring Boot web application that I launch by running this class ...
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The web app has a JSP/HTML front end served up by Spring MVC Controllers which talk to Services which talk to DAOs which uses Hibernate to read/write Entities to a MySQL database.
All the components and services get instantiated and #Autowired and the web app runs fine.
Now, I want to build JUnit tests and test some of the functionality in the Services or the DAOs.
I started writing a JUnit test like below, but I quickly got stuck on not knowing how to instantiate all the #Autowired components and classes.
public class MySQLTests {
#Test
public void test000() {
assertEquals("Here is a test for addition", 10, (7+3));
}
#Autowired
UserService userService = null;
#Test
public void test001() {
userService.doSomething("abc123");
// ...
}
}
I basically want the web application to start up and run, and then have the JUnit tests run the methods in those Services.
I need some help getting started ... is there some kind of JUnit equivalent of the #SpringBootApplication annotation that I can use in my JUnit class?
Answering my own question ... I got it working like this ...
Annotated the test class with:
#RunWith(SpringRunner.class)
#SpringBootTest
The test class had to be in a package above the #Controller class ... so my test class is in com.projectname.* and the controller is is com.projectname.controller.*
The working code looks like this ...
package com.projectname;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.projectname.controller.WebController;
#RunWith(SpringRunner.class)
#SpringBootTest
public class Test1 {
#Autowired
private WebController controller;
#Test
public void contextLoads() throws Exception {
assertNotNull("WebController should not be null", controller);
}
}

SpringBoot Junit5 fails when renaming package of class holding #SpringBootApplication annotation

I'm struggling with JUnit 5 when moving the #SpringBootApplication to a different package.
I have setup a new SpringBoot-project (2.2.1.RELEASE) with Maven and Eclipse (had to upgrade this from "Eclipse Photon" to support the SpringBoot-Release
My package layout looks like this:
/src/main/java
com.package.sample.appl1
StartSamples.java
com.package.sample.appl1.start
com.package.sample.appl1.dbaccess
com.package.sample.appl1.run
com.package.sample.appl1.utils
com.package.sample.appl2.run
com.package.sample.appl2.run
/src/test/java
com.package.sample.appl1.dbaccess
SimpleTest.java
The class holding the #SpringBootApplication is:
#ComponentScan({
"com.package.sample"
})
#SpringBootApplication
public class StartSamples {
public static void main(String[] args) {
System.out.println("Start");
try {
SpringApplication.run(StartSamples.class, args);
} catch (Exception e) {
LOGGER.error("", e);
System.exit(-1);
}
}
And the test is this:
import static org.junit.Assert.assertEquals;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.junit.jupiter.SpringExtension;
/**
* Test the Query-statements and the DAO methods
*
* #author U005078
*
*/
#SpringBootTest
#ExtendWith(SpringExtension.class)
#ComponentScan({
"com.package.sample"})
#EnableAutoConfiguration
public class SimpleTest {
#SuppressWarnings("unused")
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleTest.class);
#Test
#DisplayName("SimpleTest")
public void testTotalRows() {
With this configuration all is fine, "StartSamples" works as expected and aqlso the SimpleTest.
But when moving "StartSamples" to a different package (e.g. "com.package.sample.start" would make more sense to me - "StartSamples" is still ok but "SimpleTest" does not fail nor succeed - test seems not to become executed.
I see a message:
class path resource [com/package/sapmle/appl1/dbaccess/SimpleTest-context.xml] does not exist
class path resource [com/package/sapmle/appl1/dbaccess/SimpleTestContext.groovy] does not exist
.SimpleTest]: SimpleTest does not declare any static, non-private, non-final, nested classes annotated with #Configuration.
I also found:
Neither #ContextConfiguration nor #ContextHierarchy found for test class [com.package.sample.appl1.dbaccess.SimpleTest], using SpringBootContextLoader
So I defined the #ContextConfiguration to the "SimpleTest", then it worked. But I do not understand at all why the move of the #SpringBootApplication did change this behaviour.
With another try of setting up this project I ended up with "No tests found with test runner 'JUnit 5'" and could also not find any reason. I started over again with the current approach and get to here. And do do nat any clue what gives me the error - for either of the problems.
Any explanation witld be appreciated. I tried for lots of hours now to find something in the internet - but I only found recommendations like "try this", "try that" but no help in understanding.
So any help is appreciated.
Define your SpringBoot Main class like below
#SpringBootTest(classes = {StartSamples.class})
public class SimpleTest {
...
}

JUnit testing got initializationError with java.lang.Exception: No tests found matching

When running JUnit testing , it gave an initializationError: No tests found matching. Like this:
prodapi-main-junit
initializationError(org.junit.runner.manipulation.Filter)
java.lang.Exception: No tests found matching [{ExactMatcher:fDisplayName=testCreateSite], {ExactMatcher:fDisplayName=testCreateSite(com.company.product.api.web.rest.HostControllerTest)], {LeadingIdentifierMatcher:fClassName=com.company.product.api.web.rest.HostControllerTest,fLeadingIdentifier=testCreateSite]] from org.junit.internal.requests.ClassRequest#3c0f93f1
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:40)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createFilteredTest(JUnit4TestLoader.java:77)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.createTest(JUnit4TestLoader.java:68)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader.loadTests(JUnit4TestLoader.java:43)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:444)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
While the testing code is as below:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = ProductApplication.class)
#WebAppConfiguration
public class HostControllerTest{
#Test
public void testCreateSite() throws Exception {
......
}
}
It should be fine to load the class, running well. There're other modules similar with this one, they're fine to run.
I have checked the possible causes:
someone said that missing "Test" annotation result in this error.
While the code did have the annotation as you can see.
some said the build path should be configured to do the build under the testing source folder, getting the testing class, and export.
And that configuration I double-checked worked as well.
maybe testing classes are not generated in the compile time, while I can see those testing classes under the destination folder.
I don't know whether there're any other possible things can get Junit testing error like this. Maybe I should check the class loader?
After googled some answers. I found there's an issue talked about this case as below:
https://github.com/junit-team/junit4/issues/1277 (FilterRequest may hide the real failure cause(exception) of a test)
Here're the steps I tried:
1. don't select the testing function alone, while select "Run all the tests in the selected project" option on the Test Tab, when select the Junit project name
after click on Run->"Run(Debug) Configuration"
2. You can get the details of the error as follows:
initializationError(com.company.product.api.web.rest.HostControllerTest)
java.lang.Exception: Method testSetDBConfiguration should have no parameters
at org.junit.runners.model.FrameworkMethod.validatePublicVoidNoArg(FrameworkMethod.java:76)
at org.junit.runners.ParentRunner.validatePublicVoidNoArgMethods(ParentRunner.java:155)
3.according to the details given by eclipse above, I removed the argument of that function, the initializedError just disappeared.
So this issue rises due to the new added testing function has unnecessary input argument.
The incorrect code :
#Test
public void testSetDBConfiguration(String name) throws Exception {
Changed to
#Test
public void testSetDBConfiguration() throws Exception {
Had the same issue with PowerMock #RunWith(PowerMockRunner.class) then discovered that my #Test was the wrong implementation. Was using
import org.junit.jupiter.api.Test;
I switched to import org.junit.Test; and that fixed the problem for me.
I have found the below solution which worked for me.
your Application #SpringBootApplication package name
and Test package name should be same .
see if it helps.
Happy coding.
First able Make sure that your methods annotated #test as well as the test class are public.
I had a similar error when my test method was private. It needs to be public.
I had the similar problem and later realized that my main spring boot application configuration was not scanning through the packages that had my test classes in
Main class was scanning packages - {"com.mycmp.prj.pkg1", "com.mycmp.prj.pkg2", "com.mycmp.dependentprj.pkg5"}
Test class was in package - com.mycmp.prj.pkg3
Problem got fixed by fixing our base packages to scan all packages from current project and only scan limited needed packages from dependent libraries
Main java class
#SpringBootApplication(scanBasePackages = {"com.mycmp.prj.pkg1", "com.mycmp.prj.pkg2", "com.mycmp.dependentprj.pkg5"})
public class MyApplication extends SpringBootServletInitializer {
public static void main(final String[] args) {
SpringApplication.run(MyApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
return application.sources(MyApplication.class);
}
#Bean
public FilterRegistrationBean<Filter> customFilters() {
final FilterRegistrationBean<Filter> registration = new
FilterRegistrationBean<>();
final Filter myFilter = new ServicesFilter();
registration.setFilter(myFilter);
registration.addUrlPatterns("/myurl1/*", "/myurl2/*");
return registration;
}
#PostConstruct
public void started() {
//
}
}
My Test Class
**package com.mycmp.prj.pkg3;**
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.mongodb.MongoClient;
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MyApplication.class)
public class MongoConfigStoreTest {
#Test
public void testConnection() throws Exception {
final MongoClient client = new MongoClient("localhost", 127027);
assertNotNull(client);
assertNotNull(client.getDatabase("localhost"));
}
}
I had to add the hamcrest-all-1.3.jar into classpath to run unit test.
junit 4.12
java.lang.Exception: No tests found matching [{ExactMatcher:fDisplayName=myTest], {ExactMatcher:fDisplayName=scannerTest(example.JavaTest)], {LeadingIdentifierMatcher:fClassName=example.JavaTest,fLeadingIdentifier=myTest]] from org.junit.internal.requests.ClassRequest#38af3868
at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:40)
Check for below conditions:
Have you used org.junit.jupiter.api.Test; instead of org.junit.Test;
for running Junit 4 test cases?
Have you passed an argument to the
test method as shown below:
public void test(String arg){
assertTrue(true);
}
Re-building a project will also work:
mvn clean install
If it is a maven project run eclipse:eclipse as a Maven build.That resolved my problem.
When you use gradle (and you use codium as IDE)
you may need to rebuild it manually, e.g. with ./gradlew build.
Yup, in VSCode Testing view, I often get the horrible red "InitializationError" for my Java JUnit-based JPA tests and could never figure it out. Based on Mohit Basak comment, I changed
#SpringBootTest(classes = {MyApp.class})
public class MyTest {
...
}
to
#SpringBootTest(classes = {com.xyz.MyApp.class})
public class MyTest {
...
}
and so far I think it's working better now. The tests always ran green/complete and even runs fine from command line with gradle build

How to make Spring IoC container available through out project

I feel stupid to even ask for this but I spent days looking for the answer and I'm still with nothing.
I wanna include simple Spring IoC container in my project. All I want it to do is to allow me Injecting/Autowiring some reusable objects in other classes. What I've done so far looks like this:
-> Project structure here <-
Configuration code:
package com.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import java.util.Random;
#Configuration
#ComponentScan(basePackages = "com.example")
public class AppConfig {
#Bean
public Random rand() {
return new Random(42);
}
#Bean
public String string() {
return "Hello World!";
}
}
Main class code:
package com.example;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Random;
public class Main {
#Autowired
Random rand;
#Autowired
String string;
public static void main(String[] args) {
// workflow
Main main = new Main();
System.out.println(main.string);
}
}
AnotherClass code:
package com.example.deeperpackage;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Random;
public class AnotherClass {
#Autowired
Random rand;
#Autowired
String string;
public void methodToBeCalled() {
// TODO
System.out.println(string);
}
}
How can I make these #Autowired annotations work? Do I have to instantiate container in every single class in which I want to autowire components? I've seen in work a oracle app which used Spring and #Inject to distribute objects to numerous classes and there was no container logic in any class available for me. Just fields with #Inject annotation. How to achieve that?
Simply add the annotation #Component on the classes you want to inject :
#Component
public class AnotherClass {
...
}
But you cannot inject static attributes and when you do new Main(), no Spring context is being created. If you use Spring Boot, you should look at how to write a main with it.
https://spring.io/guides/gs/spring-boot/

how to use the ApplicationArguments in spring-boot

I am learning the Spring-Boot(I am new to it), reading the Spring Boot Document. In the 23.6 Accessing application arguments, It talk about the ApplicationArguments, and the code is:
package com.example.project;
import org.springframework.boot.*;
import org.springframework.beans.factory.annotation.*;
import org.springframework.stereotype.*;
import java.util.*;
#Component
public class MyBean {
#Autowired
public MyBean(ApplicationArguments args) {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
System.out.println(debug);
System.out.println(files);
}
}
It says if run with "--debug logfile.txt" debug=true, files=["logfile.txt"].
But in my project, I don't know how to run it. I create the spring-boot using Maven: The Project Structure
In Spring Boot doc ApplicationArguments is autowired in a bean. Here is a more hands on example where it's used in a Main method.
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application implements ApplicationRunner {
public static void main(String[] args) {
SpringApplication.run(Application.class, args).stop();
}
#Override
public void run(ApplicationArguments args) throws Exception {
boolean debug = args.containsOption("debug");
List<String> files = args.getNonOptionArgs();
System.out.println(debug);
System.out.println(files);
}
}
Assuming that you have an Application class with annotation #SpringBootApplication like in the answer provided by a.b.d.
To be able to provide the arguments within IntelliJ IDEA environment you will need to first Run the main method and then Edit 'Run/Debug Configurations' and under Main Class fill Program arguments field with "--debug logfile.txt":
In one word like a thousand :
the 'Program arguments' in your IDE field prefixed by -- is simply the same name as the 'Option' expected in the 'ApplicationArguments'.
Hence you can match --debug and "args.containsOption("debug")".

Resources