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

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

Related

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

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

How do I get JMeter Junit Request Sampler to run #BeforeClass?

I have the following Test class...
#RunWith(JUnit4.class)
public class AdminSpecTest extends BaseTest{
#BeforeClass
public static void getLogin(){
System.out.println("getLogin");
...
}
#Test
public void testAdminPage(){
System.out.println("testAdmin");
...
}
}
When I try to create a JUnit sampler in JMeter I run the test and it fails. In the terminal window I see...
testAdmin
but there is no getLogin. Why isn't BeforeClass getting called? Can I get this to happen?
Accoding to JMeter's JUnit you can use #Before instead for setup before test executes.
The following JUnit4 annotations are recognised:
#Before
treated the same as setUp() in JUnit3
#BeforeClass, #AfterClass
treated as test methods so they can be run independently as required
Yes you should be able to do this, but this solution involves adding another class at least temporarily while you are performance testing with JMeter. You then use this class to call the other test class (AdminSpecTest). Make sure you select this new class and method in JMeter's Junit Sampler dropdowns.
package test;
import org.junit.Test;
import org.junit.runner.JUnitCore;
public class TestRunner
{
public TestRunner()
{
}
#Test
public void runTests()
{
JUnitCore junit = new JUnitCore();
junit.run(AdminSpecTest.class);
}
}

#WebMvcTest mapperscan conflict

My project used spring-boot (1.4.0.release) and mybatis-spring-boot-starter. When I try to have some test code for controller, I always get a exception
Caused by: java.lang.IllegalArgumentException: Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
at org.springframework.util.Assert.notNull(Assert.java:115)
at org.mybatis.spring.support.SqlSessionDaoSupport.checkDaoConfig(SqlSessionDaoSupport.java:75)
at org.mybatis.spring.mapper.MapperFactoryBean.checkDaoConfig(MapperFactoryBean.java:74)
at org.springframework.dao.support.DaoSupport.afterPropertiesSet(DaoSupport.java:44)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
... 42 more`
But when I comment #MapperScan("com.toby.mapper"), it runs very well.
Here is my example class:
#MapperScan("com.toby.mapper")
#EnableTransactionManagement
#EnableConfigurationProperties(AppConfig.class)
#SpringBootApplication(scanBasePackages = "com.toby.configuration,com.toby.web.controller,com.toby.service,com.toby.dao")
public class Example {
public static void main(String[] args) throws Exception {
//new SpringApplicationBuilder().sources(Example.class).run(args);
SpringApplication application=new SpringApplication(Example.class);
application.addInitializers(new PropertyPasswordDecodingContextInitializer());
application.run(args);
}
}
Here is my test code:
package com.toby.web.controller;
import com.toby.common.config.AppConfig;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
/**
* Created by Toby on 2016/8/10.
*/
#RunWith(SpringRunner.class)
#WebMvcTest(value = MyRestController.class)
public class MyRestControllerTests {
#Autowired
private MockMvc mvc;
#MockBean
private AppConfig appConfig;
#Test
public void testHome() throws Exception {
/*this.mvc.perform(get("/users").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk()).andExpect(content().string("Honda Civic"));*/
}
}
I guess you've updated the description or I didn't read it properly the first time. #MapperScan is a mybatis specific annotation that triggers something but is missing some guard of some sort.
We had the same problem in boot actually. Let's say you put #EnableCaching on your main app. Because slicing disables all auto-configurations but a list of specific ones, the cache auto-configuration would not kick in and you'll get an exception because the CacheManager isn't found. To fix that issue, we've started to create some annotation to easily enable those. If you look at WebMbcTest you'll see it's annotated with AutoConfigureCache that's going to provide a dummy no-op cache manager unless specified otherwise.
Your problem is that the mybatis support is a third party integration and there isn't any support for that. Some solutions:
Change #WebMbvcTest to provide the class of another configuration class, effectivly disabling the use of your main spring boot app. Of course that class shouldn't define the #MapperScan annotation
Move the MapperScan (and anything that's not required with slicing) to another Configuration class. It could be a class in the same package as your app. Slicing won't scan those by default so you'll be fine. It's by far the easiest
Create an issue in the mybatis support so that they improve the auto-configuration to back-off (prevent this exception). I am not sure that's possible actually
Long story short, since #MapperScan is a way to tell mybatis to scan your entities, maybe you shouldn't add it on your main boot app if you use slicing. Because your #WebMbcTest doesn't want to use that obviously.

Multiple ApplicationRunners on classpath, how to make SpringApplication.run() only run one

Context: I have a project with some utilities to do things like data fixing. Each utility is a Java application, i.e. class with main() method. I want to define them as Spring Boot applications so I can use the ApplicationRunner and ApplicationArguments facility. The Spring configuration is defined via annotations in a shared configuration class. I've put a minimal example of this setup below.
Expectation: if I call SpringApplication.run(SomeClass.class, args) where SomeClass is an ApplicationRunner, it runs the run() on that class and not on any other classes that may be in the app context.
What actually happens: it calls all ApplicationRunners that it has in the context.
Why? I understood SpringApplication.run(Class, String[]) to mean, "run this class" whereas it appears to mean "load an app context from this class and run anything you can find in it". How should I fix it to run only 1 class? I don't mind if my other application class isn't in the app context, because all the configuration I need is in the shared config class. But I don't want to have to edit code (e.g. add or remove annotations) according to which class I need to run.
Minimal example:
A Spring config class (shared):
package com.stackoverflow.example;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class ExampleSpringConfig {
/** Some bean - just here to check that beans from this config are injected */
#Bean public FooService fooService () {
return new FooService();
}
}
Two application classes
package com.stackoverflow.example;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.annotation.Resource;
#SpringBootApplication
public class SomethingJob implements ApplicationRunner {
#Resource private FooService fooService;
public void run(ApplicationArguments args) throws Exception {
System.out.println("Doing something"); // do things with FooService here
}
public static void main(String[] args) {
SpringApplication.run(SomethingJob.class, args);
}
}
and another that is identical except that it prints "Doing something else".
Output:
[Spring Boot startup logs...]
Doing something else
Doing something
[Spring Boot shutdown logs...]
Firstly, only one class should be annotated with #SpringBootApplication. As you've noticed in your answer, this defines the external "main" entry point. I would recommend this is a different class to your ApplicationRunner classes for clarity and conceptual separation.
To only have some but not all runners run, I've done this by parsing the arguments, and quickly exiting from the runner which should not be called. e.g.
package com.stackoverflow.example;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.annotation.Resource;
#Component
public class SomethingJob implements ApplicationRunner {
#Resource private FooService fooService;
public void run(ApplicationArguments args) throws Exception {
if (!args.containsOption("something")) return
System.out.println("Doing something"); // do things with FooService here
}
}
That way you can do java -jar myjar.jar --something or java -jar myjar.jar --something-else depending which one you want to be run.
I found a workaround while experimenting with my minimal example.
#SpringBootApplication is just an alias for #ComponentScan, #EnableAutoConfiguration and #Configuration. By applying them separately, I discovered that it's the #Configuration annotation that causes this behaviour. If I only apply the other 2, I don't get the issue.
I guess this is because #Configuration means "I'm a configuration class, and any beans I define should be pulled into the context during component scan" and although this class doesn't define an ApplicationRunner, it is one, which has the same effect. Therefore if you have 2 such beans on the classpath, they both get pulled into the app context.
Without #Configuration, the bean you want to run still gets registered since it's referenced by the call to run(), but other ApplicationRunners on the classpath don't.
This fixes my immediate problem by making sure I only have one ApplicationRunner in my app context. But it doesn't answer the wider question, "If I do have several ApplicationRunners, how do I tell Spring Boot which one to run?" So I'd still appreciate any more complete answer or suggestions for a different approach.

Sonar complains about Spring Boot configuration

I have this class to start up the spring-cloud config server. It is a spring-boot application.
#SpringBootApplication
#EnableConfigServer
#EnableDiscoveryClient
public class ConfigServerApplication {
public static void main( String[] args ) {
SpringApplication.run( ConfigServerApplication.class, args );
}
}
The application runs fine and all my unit tests are fine. However, in our bamboo pipeline, it will initial a sonar process to analyze the code. We keep getting these minor warnings indicating the following:
Utility classes should not have a public constructor
I know that this is a minor issue, but I have been tasked with removing these from our code.
Ideally, you would mark the class final and provide a private constructor, or so all searches provide as a solution. However, a Spring Configuration class cannot be made final and cannot have a private constructor.
Any ideas how to resolve this?
I'm afraid this isn't a problem spring-boot or spring-cloud can solve. You need to add exceptions to your sonar configuration.
Adjusting your sonar settings would be a nicer approach of course, but if you want to please the machine spirits, you can simply add a non-static dummy function to your class, making it "non-utility" in the eyes of the Sonar checker.
It's easy to test:
#RunWith(SpringRunner.class)
#SpringBootTest
public class YourApplicationTest {
#Test
public void shouldLoadApplicationContext() {
}
#Test
public void applicationTest() {
YourApplication.main(new String[] {});
}
}
Now Sonar is saying, this is tested!
(Kudos goes out to: Robert # https://stackoverflow.com/a/41775613/863403)

Resources