SpringBootTest for DAO JUnit test - java

I am attempting the following unit test of a DAO.
I am unable to get the DataSource recognized.
Can I get a tip on how to resolve this?
Details below
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class EntityDaoTest {
#Autowired
protected EntityDao entityDao;
#Before
public void setup()
{
}
#Test
public void test() throws InternalServerException
{
List<Entity> entities = entityDao.list();
assert(entities.size()==0);
}
}
The relevant aspects of the DAO class are as follows
#Repository
public class EntityDao extends GenericDao<Entity>{
public EntityDao(DataSource dataSource) {/.../}
}
My src/test/resources/application.properties file is as follows
# Database
spring.datasource.url=jdbc:mysql://localhost:3306/db
spring.datasource.username=dbuser
spring.datasource.password=dbpass
Trace from running as JUnit test in Eclipse
java.lang.IllegalStateException: Failed to load ApplicationContext
...
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityController': Unsatisfied dependency expressed through field 'entityDao': Error creating bean with name 'entityDao' defined in file .../target/classes/hitstpa/dao/EntityDao.class]: Unsatisfied dependency expressed through constructor parameter 0: No qualifying bean of type [javax.sql.DataSource] found for dependency [javax.sql.DataSource]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {};
...
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'entityDao' defined in file [/home/fmason/workspace/hitstpa/target/classes/hitstpa/dao/EntityDao.class]: Unsatisfied dependency expressed through constructor parameter 0: No qualifying bean of type [javax.sql.DataSource] found for dependency [javax.sql.DataSource]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency [javax.sql.DataSource]: expected at least 1 bean which qualifies as autowire candidate for this dependency. ...`
Application structure
-src
--main
---java
----Application.java
----com
----hitstpa
-----controller
-----dao
------EntityDao.java
-----model
---resources
----application.properties
--test
---java
----hitstpa
-----dao
------EntityDaoTestDOTjava
---resources
----applicationDOTproperties

First of all for integration tests you need an integration Db with some fixed data.
Now you need to create a configuration class which will create the
integration test specific dependencies(I have named it as DbConfig
.java)
Next is add #ContextConfiguration annotation to the integration test
class and provide DbConfig.java, so that when test runs it will
create the datasource dependency and inject it to the container
Sample Code
#Configuration
public class DbConfig {
#Bean
public DataSource dataSource() {
//Create the DataSource with integration-DB properties
return dataSource;
}
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
#ContextConfiguration(classes=DbConfig.class)
public class EntityDaoTest {
}

For the record, I believe this is not a good unit test. This test requires that a mysql databases exists on localhost.
Anyhow, the errors suggest that the Spring Context isn't loaded correctly. When using SpringBootTest, Spring looks for the configuration using the test's package as root. So, if it's lower than your Configuration classes, it won't them.
Take a look at Spring's documentation:
The search algorithm works up from the package that contains the test
until it finds a #SpringBootApplication or #SpringBootConfiguration
annotated class. As long as you’ve structure your code in a sensible
way your main configuration is usually found.
Solution:
You can either move your tests to the same level as your SpringBoot Main class or change it to: #SpringBootTest(classes = YourSpringBootMainClass.class)

Related

Bean is no longer being autowired after Spring 5.3 Upgrade

I upgraded my package from Spring 4.3 to Spring 5.3 which has caused a issue I am completely to solve, for some reason a Bean that is created and works under 4.3 is being created, but not wired in. The bean is being created, and the configuration has not changed, yet it doesn't work?
Bean Creation:
#Configuration
#SuppressWarnings("checkstyle:HideUtilityClassConstructor")
#Slf4j
public class EnvironmentConfig {
#Bean
public static AppEnvironmentHelper environmentHelper() throws IOException {
final AppEnvironmentHelper.Config config = new AppConfigEnvironmentHelper.Confg()
// Config object is configured
return new AppEnvironmentHelper(config);
}
}
Attempted Injection of Bean:
#Configuration
#Slf4j
public class OtherConfig {
#Value("${role}")
private String someRole;
#Value("${port}")
private String somePort;
#Autowired
private EnvironmentHelper environmentHelper;
.......
}
The class path for the bean is in the configuration, and when launching the service I see logs that indicate that EnviromentConfig is created before OtherConfig
org.springframework.beans.factory.support.DefaultListableBeanFactory: Finished creating instance of bean 'environmentHelper'
But I always get
UnsatisfiedDependencyException: Error creating bean with name 'OtherConfig': Unsatisfied dependency expressed through field 'environmentHelper'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.amazon.coral.spring.EnvironmentHelper' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
After it errors spring goes to clean up the beans with
Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#40db2a24: defining beans [.....,EnvironmentConfig, environmentHelper ]
Which seems to indicate to me that it is finding the bean, its creating the bean, but then when it comes to wire in enviromentHelper it doesnt find it. Ive tried naming the bean using qualifiers but that did nothing. And I wrapped the EnviromentHelper and added logs during creation of the bean and destruction, so I know the bean isnt being destroyed prematurely. Im not certain what else to try to troubleshoot further.

#Component not being read in Spring test

I created an Integration test to test the new feature I just added but the Spring wiring is not working. The unit tests all work and the existing Spring integration tests still work but I am unable to Autowire my new class
Here is the error message –
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.xxx.xxx.etc.MyNewClassTest’: Unsatisfied dependency expressed through field 'sut'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.xxx.xxx.etc.MyNewClass ' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
The new class –
#Slf4j
#Component
public class MyNewClass extends AbstractRetryJob<Event> {
My test -
#ExtendWith(SpringExtension.class)
class MyNewClassTest {
#Autowired private MyNewClass sut;
Any idea on what is going wrong?
Adding #ExtendWith(SpringExtension.class) is not enough to create the Spring context. You need to add #SpringBootTest to your MyNewClassTest. Per the appropriate comment, you can drop #ExtendWith(SpringExtension.class)
#SpringBootTest
class MyNewClassTest {
#Autowired private MyNewClass sut;
}

How to add a protected configuration with access to properties to a Spring Boot Test context?

i use JUnit 5 with Spring Boot 2.5.2 . Now i want to write a Unit test, that does not load the full Application context.
Therefore i annotate my test like that:
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {ConfigurationA.class})
class Test1{
...
}
In ConfigurationA the Bean1 gets created.
The Problem is that the ConfigurationA accesses an ConfigurationB for creating Bean1, but ConfigurationB is protected.
Now i get the following Error:
Error creating bean with name 'Bean1' defined in com.package.sample.config.ConfigurationA: Unsatisfied dependency expressed through method 'createBean1' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.package.sample.config.ConfigurationB available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
When i change #ContextConfiguration... to #SpringBootTest it works but the whole Context gets loaded.
Is there any solution to load not the whole context?
Just make ConfigurationA extend ConfigurationB

Spring test integration not run how I deal with this error?

I have a test class that make me crazy with this error :
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name .imprimirRelatorio: Unsatisfied
dependency expressed through field repository; nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type v1.teste.Service available: expected at least
1 bean which qualifies as autowire candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
After search in the web by a resolution, I couldn't run the test. The test class was like that:
#RunWith(SpringJUnit4ClassRunner.class)
public class imprimirRelatorio {
#Autowired
PautaService pautaRepository;
#Test
public void imprimirCabecalho(){
PautaReportBuilder pautaReportBuilder = new PautaReportBuilder();
//Reuniao reuniao = reuniaoService.findOne(UUID.fromString("4c7d3fc8-f78d-4ed3-a1ad-83c5da822ea7"));
try {
pautaReportBuilder.cabecalhoRelatorios(reuniao);
} catch (Exception e)
{
e.printStackTrace();
}
}
}
/*
Update
*/
So I forgot to say that I already tried the annotation #service in the pautaService interface. And the same on the test class I've tried to use the #SpringBootTest annotation. So the error messages was different.
The App.class
#SpringBootApplication
#ComponentScan({"br.com.empresa123.sistema123.*"})
public class App { public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
The interface PautaService:
#Service
public interface PautaService {
Page<Pauta> findAll(Pageable page);
Pauta findOne(UUID uuid);
Pauta save(Pauta pauta);
}
This is the first approach of my test , the nested exception were :
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'subjectController': Unsatisfied
dependency expressed through field 'subjectService'; nested exception
is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'subjectService': Unsatisfied dependency
expressed through field 'domainSvc'; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'dominio': Unsatisfied dependency
expressed through field 'domainRepo'; nested exception is
org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'domainReposImpl': Unsatisfied
dependency expressed through field 'sqlGenericPager'; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException: No
qualifying bean of type 'java.lang.String' available: expected at
least 1 bean which qualifies as autowire candidate. Dependency
annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true),
#org.springframework.beans.factory.annotation.Qualifier(value=sql-Generic-Pager)}
For integration test, add #SpringBootTest over your class.
In case where your file is not in the same packaging of your app, #ComponentScan() your app packaging.
I think you have forgot to annotate the service with the #Service annotation. If so, please tag the Service CLASS with #Service.
I solve this problem when I search by a annotation lost in my code that I never used it :
public abstract class BaseCustomRepository {
// the class code
#Autowired
#Qualifier("sql-Generic-Pager")
protected String sqlGenericPager;
}
I never used a Custom repository implementation so I will rethink what I will do with this class. Thanks a lot of the coders that lost their time to help me and the stack over flow to share my concerns.
I was laughing about this question, all the trouble was caused by me, like you do a git blame command in a class and see your user that made the wrong code.

No qualifying bean of type 'springfox.documentation.schema.TypeNameExtractor'

I'm trying to implement Swagger using the JHipster implementation as reference into my Kotlin application.
However, when I run my tests, I get the following error for most of my tests (these tests work fine if I remove this swagger code):
Caused by:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'pageableParameterBuilderPlugin' defined in class path resource [com/application/config/apidoc/SwaggerPluginsAutoConfiguration$SpringPagePluginConfiguration.class]: Unsatisfied dependency expressed through method 'pageableParameterBuilderPlugin' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'springfox.documentation.schema.TypeNameExtractor' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
My SwaggerPluginsAutoConfiguration class:
#Configuration
#ConditionalOnWebApplication
#ConditionalOnBean(Docket::class)
#AutoConfigureAfter(SwaggerAutoConfiguration::class)
class SwaggerPluginsAutoConfiguration {
#Configuration
#ConditionalOnClass(Pageable::class)
class SpringPagePluginConfiguration {
#Bean
#ConditionalOnMissingBean
fun pageableParameterBuilderPlugin(typeNameExtractor: TypeNameExtractor,
typeResolver: TypeResolver): PageableParameterBuilderPlugin {
return PageableParameterBuilderPlugin(typeNameExtractor, typeResolver)
}
}
}
The SwaggerAutoConfiguration class:
#Configuration
#ConditionalOnWebApplication
#ConditionalOnClass(ApiInfo::class, BeanValidatorPluginsConfiguration::class, Servlet::class, DispatcherServlet::class)
#Profile(value = [SPRING_PROFILE_SWAGGER])
#EnableSwagger2
#Import(BeanValidatorPluginsConfiguration::class)
class SwaggerAutoConfiguration(applicationProperties: ApplicationProperties) {
...
}
If I include the swagger profile in my tests application config file, the tests pass. However, if the profile isn't present, the tests fail with the error above. I'm not sure why Spring is trying to configure swagger if the profile isn't set.
How can I set this up, so that the configuration doesn't try to load if the profile isn't specified?

Categories