How to autowire a spring DAO repository in its unit test? - spring-boot

I am experimenting Spring's reactive support for DB operations. So I have created a repository as:
public interface FeatureRepository extends ReactiveCrudRepository<Feature, UUID> {}
Now I want to test it through a unit test.
So my test is:
#ExtendWith(SpringExtension.class)
#SpringBootTest
public class FeatureRepositoryTest {
#Autowired
FeatureRepository featureRepository;
.....
}
But I get error:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of
type 'x.y.z.FeatureRepository' available: expected at least 1 bean which
qualifies as autowire candidate. Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
How can I solve this issue?

Your DAO is managed as any other tested class, so without defining a specific ApplicationContext in your test runtime, Spring do nothing and the FeatureRepository bean is not known.
2 approaches :
Your test is more about integration test, so your test runtime need to be specify.
Your test is more about unit test, I suggest you to mock your repository (pragrammatically or using framework like Mockito)
Regards.

Related

Unable to Autowire brave.Tracer inside Spring boot Application

I am working on Spring boot application and I tried to Autowire Tracer object to get the traceId, but its raised the following exception. why??
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'brave.Tracer' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I used the Tracer in a lot of projects and its always working with no issues!!
Spring boot container is not able to resolve the implementation of your autowired interface in this case. Please annotate your implementation class with spring stereotype annotations.
For e.g We provide #Reposiory for dao classes, #Service for service classes & #Component as a generic one. This will solve your problem. If you still face any issues, Just share your code snippet.

Application Context is failing to load, as it is not finding any qualifying bean of type EntityManager

While running JUnits, ApplicationContext is not loaded, as it could not find a qualifying bean javax.persistence.EntityManager. However, the application for which the Junit is being written is working. Both the application and JUnits are using the same spring configuration.
My Configuration class looks like below
#Configuration
#EnableTransactionManagement
public class AppConfiguration {
#Autowired private EntityManager entityManager;
#Override #Bean
public CustomRepository<Person> customRepository(){
return new CustomRepository<>(Person.class, entityManager);
}
As you see, I'm able to autowire EntityManager, even though I have not explicitly defined the bean and the application is working without any issues.
Now in my JUnit
#RunWith(SpringRunner.class)
#ContextConfiguration(classes=AppConfiguration.class)
#TestPropertySource(locations = "classpath:application.properties")
public class ControllerTest {
#Autowired
private CController controller;
As you see both application and my Junit are using same configuration. How ever when running JUnit, I'm seeing
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManager' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I could not understand what in the JUnit is causing the isssue, while the aplication is still working.
Thanks
it clearly means that EntityManager bean is not defined in your application context.
So either you define it by yourself or let Spring-boot do the lifting(Spring-boot auto config your context based on dependencies in your POM file). If you choose the latter option then one option to get rid of the error by adding H2 DB.
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
UPDATE:
In your test, instead of initializing your context using #ContextConfiguration do that with #SpringBootTest it will bootstrap your entire container(including other beans that are not defined in AppConfiguration.java). Read more about in spring-docs

Spring componentscan for multiple packages

I want Spring to perform dependency injection from 2 different projects and have a main #Configuration annotated class as below -
#Configuration
#EnableWebMvc
#ComponentScan(value = { "com.x.y", "com.a.b" })
public class AppConfig {
}
Classes under com.x.y is part of packages which contains AppConfig class but classes under com.a.b are part of different jar which is packaged under war file containing AppConfig class.
When i am deploying war file i am getting error as -
Unsatisfied dependency expressed through constructor argument with index 0 of
type [com.a.b.c.d.ClassA]: No qualifying bean of type [com.a.b.c.d.ClassA]
found for dependency: expected at least 1 bean which qualifies as autowire
candidate for this dependency. Dependency annotations: {}; nested exception
is org.springframework.beans.factory.NoSuchBeanDefinitionException:
I am not sure what is wrong in my way of using #ComponentScan. Looking for inputs from Spring experts.
Thanks

Spring initialization done outside the project

I have a java spring project . I see that one way of initialing the spring project is using this code in the main method.
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(Config.class);
ctx.scan("com.example.db.app");
ctx.refresh();
Is it possible to keep this outside a main method and then make a jar of this project. Add it as a dependency in pom.xml in other project and call the method which initializes the spring artifacts from there.
I tried doing it. I am getting an error.
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'itemInformationRepositoryService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void com.example.db.app.service.ItemInformationRepositoryService.setItemInformationRepositoryService(com.example.db.app.repository.ItemInformationRepository); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.example.db.app.repository.ItemInformationRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
The exception message states:
No qualifying bean of type [com.example.db.app.repository.ItemInformationRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency.
This means that the class com.example.db.app.repository.ItemInformationRepository is not in the Spring context. Perhaps you were expecting Spring to discover this class as a result of your instruction to Spring to scan com.example.db.app? According to the Javadocs for AnnotationConfigApplicationContext.scan() ...
Perform a scan within the specified base packages.
#param basePackages the packages to check for annotated classes
So, in order for Spring to discover com.example.db.app.repository.ItemInformationRepository you must either:
Annotate it with org.springframework.stereotype.Component so that it is discovered by scan()
Register it in the same way as you are registering Config.class e.g. ctx.register(ItemInformationRepository.class);

How to use inject resource from server (like ManagedExecutorService) in Junit-Test of Spring

I use ManagedExecutorService for concurrency in my code like this:
#Resource
private ManagedExecutorService defaultManagedExecutorService;
It works fine if I build them and deploy them on my server, because the i reference the resource ManagedExecutorService on the server:
<managed-executor-service name="default" jndi-name="java:jboss/ee/concurrency/executor/default" context-service="default" hung-task-threshold="60000" core-threads="5" max-threads="25" keepalive-time="5000"/>
But I have my Junit test based on Spring. And to run this test I don't need any server. So I got the following exception:
Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.enterprise.concurrent.ManagedExecutorService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#javax.annotation.Resource(mappedName=, shareable=true, description=, name=, type=class java.lang.Object, authenticationType=CONTAINER, lookup=)}
It seems that the spring can not find my resource from the server.
What can I do now?
Thank you!
You need to "mock" that functionality, meaning simulate the real deal with a similar implementation that doesn't actually go to the server and retrieve the JNDI resource, but uses a fake result.
There is a package in Spring that offers some functionality for testing JNDI resources, you can find its source code here.
To get started with using classes in that package, I would look at Spring's own testing classes where those JNDI mocking classes are used. For example, see here how those classes are used to test a JTA transaction manager.
I haven actually used this, but I would try something like this:
import static org.mockito.BDDMockito.*;
....
ManagedExecutorService mes = mock(ManagedExecutorService.class);
ExpectedLookupTemplate jndiTemplate = new ExpectedLookupTemplate();
jndiTemplate.addObject("java:jboss/ee/concurrency/executor/default", mes);
...
Or you can take a look at this for another testing class that needs to mock a ManagedExecutorService.

Resources