I have defined a class with annotation #Configuration and some bean methods in it. This class is inside the test folder. So when I run the application will these beans be loaded by SpringBoot?
I have a class I want to test if it uses the right Beans when a certain profile is active. Therefore I have written a test class, with the profile active, for the DomesticService (which in turn uses the GardeningService and CleaningService, all of it is autowired).
#Component
public class HumanDomesticService implements DomesticService {
private CleaningService cleaningService;
private GardeningService gardeningService;
private Logger logger;
HumanDomesticService() {
}
#Autowired
public HumanDomesticService(CleaningService cleaningService, GardeningService gardeningService, Logger logger) {
setCleaningService(cleaningService);
setGardeningService(gardeningService);
setLogger(logger);
}
I made a test configuration class, which should scan the whole project for Beans, since the SpringBootApplication annotation includes the ComponentScan annotation.
#SpringBootApplication
public class ActiveProfileConfig {
}
Yet my test class can't seem to find the right Beans to complete the test.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'be.mycompany.springlessons.housekeeping.domestic.service.ActiveProfileSmallHouseTest': Unsatisfied dependency expressed through field 'service'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'be.mycompany.springlessons.housekeeping.domestic.service.DomesticService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
After that I tried to make Beans inside my configuration class, which makes my tests succeed, but then Maven complains about finding 2 Beans which could be injected there. Maven seems to be able to see all the beans through the ComponentScan.
Finally I ended importing the necessary classes, which works for both my tests and Maven, but it just doesn't seem to be the right and best solution.
#SpringBootTest(classes = ActiveProfileConfig.class)
#ActiveProfiles(profiles = "smallHouse")
#Import({HumanDomesticService.class, HumanCleaningService.class, RobotCleaningService.class, HumanGardeningService.class, HedgeTrimmerFactory.class, Broom.class, VacuumCleaner.class,
Sponge.class, DisposableDuster.class, LawnMower.class, LoggerFactory.class})
public class ActiveProfileSmallHouseTest {
#Autowired
private DomesticService service;
I have tried to search on the internet for another solution and saw I wasn't the only one with the problem, but no other solution seemed yet to have worked.
What is the reason ComponentScan doesn't seem to work in a test class and how best to solve this?
I wanted to share our final solution on this.
We both use IntelliJ IDEA as IDE. In this IDE we didn't specify that the tests shouldn't use the module path. IntelliJ now has a setting that lets you enable/disable the usage of the module path for Unit tests.
In maven we already disabled this by configuring the main surefire plugin to not use the module path.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<useModulePath>false</useModulePath>
</configuration>
</plugin>
With this 'new' feature in our IDEA, we also have to do disable this so our tests don't use the class path.
We figured it out because our Maven phase : mvn test
Did run the tests.
Now all the tests run smoothly with just the #SpringBootTest annotation.
To set this in IntelliJ :
in the menu bar : Run > Edit Configurations
in the left menu open the sub menu of Templates > JUnit
uncheck the checkbox next to Use module path
click apply > OK
From now on, all the tests you will run will not use this module path.
If you already have existing tests. Select them win the menu on the left, and uncheck the Use module path option for all of them.
I have had the exact same problem for a long time. I was able to solve this in Spring Boot by adding the main configuration I wanted to use. and all the needed dependencies my test had (All AutoWires) to the classes field of the #SpringBootTest annotation.
#SpringBootTest(classes = {ActiveProfile.class, HumanDomesticService.class, HumanCleaningService.class, RobotCleaningService.class, HumanGardeningService.class, HedgeTrimmerFactory.class, Broom.class, VacuumCleaner.class,
Sponge.class, DisposableDuster.class, LawnMower.class, LoggerFactory.class})
#ActiveProfiles({"smallhouse"})
public class ActiveProfileSmallHouseTest {
#Autowired
private DomesticService service;
...
}
If you weren't using Spring Boot. You could solve this with the #ContextConfiguration annotation. Which works in the same way and is a part of the #SpringBootTest annotation as well.
This is also how it is being done in my main learning source: Pro Spring 5 - Iuliana Cosmina et al - Apress (page 631)
I still don't know why the ComponentScan or automatic loading of the context doesn't work. But at least I know that this way my tests will always run. Also, you are able to run only the classes you need to get this test succeeding, and don't need to fire up the entire context for the test.
I'm new to Spring boot (version 1.1.8, spring version 4.0.7) and I need to fix a unit test. The class under test uses another class that has a simple autowired configuration bean. The class of the bean basically looks for a bunch of key value pairs where the keys have a certain prefix. The code itself works perfectly fine using the yaml file in src/main/resources. However, when I run the test case, this bean is null. How do I get the test case to read the yaml file in the src/test/resources directory?
You can use #TestPropertySource annotation for your test class:
#TestPropertySource(locations = "classpath:your-tets-properties-file.yml")
When running tests in a spring boot based application, spring is unable to create the datasource bean:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$NonEmbeddedConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.sql.DataSource]: Factory method 'dataSource' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Cannot determine embedded database driver class for database type NONE. If you want an embedded database please put a supported one on the classpath.
Reading this error it is clear to me, I think, that spring did not read my application.properties file located at:
src/test/resources/application.properties
For clairity, I do not want to make use of an in memory database when running my integration tests, for application specific reasons.
This file contains:
spring.datasource.url=jdbc:mysql://127.0.2.1:3306/project-test
spring.datasource.username=foo
spring.datasource.password=bar
spring.datasource.driverClassName=org.mariadb.jdbc.Driver
While when starting the application using bootRun at does read out
src/main/resources/application.properties
and does create the datasource correctly.
My tests are based on cucumber and started using the following class:
#RunWith(Cucumber.class)
public class AcceptanceTests {
}
The test context is started using the following annotations on a BaseSteps class which each class defining cucumber tests inherits from
#WebAppConfiguration
#ContextConfiguration(classes = App.class)
The spring context is started successfuly but it was unable to find my application.properties file and/or use it.
I found the solution.
I added changed the ContextConfiguration like so:
#ContextConfiguration(classes = App.class, loader = SpringApplicationContextLoader.class)
Use #SpringApplicationConfiguration instead of ContextConfiguration. This is needed for Spring-boot application tests.
I have a Spring MVC application with multiple separate modules which all have their own JavaConfig #Configuration class. My goal is to load all spring configurations that are present in the war. Depending on options passed to the build command some modules and thus configurations may not be present and so #Import isn't an option as it would throw ClassDefNotFound.
In the spring documentation it says
#Configuration is meta-annotated with #Component, therefore #Configuration classes are candidates for component scanning (typically using Spring XML's element) and therefore may also take advantage of #Autowired/#Inject at the field and method level (but not at the constructor level).
#Configuration classes may not only be bootstrapped using component scanning, but may also themselves configure component scanning using the #ComponentScan annotation:
However the main application class entry point looks like this
#Configuration
#EnableWebMvc
#EnableAutoConfiguration
#ComponentScan(basePackages="com.svims.common.web.config")
public class Application extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
And there is another class with the #Configuration annotation in the com.svims.common.web.config package that isn't found or the beans inside this configuration just aren't loaded.
I have tried adding this to the main application class
#ComponentScan(basePackages="com.svims.common.web.config",
includeFilters = {#ComponentScan.Filter( Configuration.class ) })
To ensure the scan is configured to find these types of classes but it still doesn't work.
I can only assume that Spring MVC bootstraps in a way as to ignore these configurations but I can't find any reference to this in the documentation.
Does anyone know what is going on or any suggestions on how I might do this?
Always check the packages being scanned again and again.