Test application cannot find autowired bean in same project - spring

I have a jar file that is the persistence layer, ad I just want to test the DAO that are simply autowired into other service layer clasees. But I want to test without any mocking or whatever.
I think this should be pretty simple. I have this in my srs/test/java
#RunWith(SpringRunner.class)
#ComponentScan("com.xxxx")
public class ApplicationTester {
#Autowired
AplicationDocumentDao aplicationDocumentDao;
#Test
private void testAplicationDocumentDao() {
aplicationDocumentDao.allForOrg(1);
}
}
All the DAO's are in the same projust under the usual /src/main/java
When I run the mvn to just run the tests like this:
mvn -Dtest=ApplicationTester test
I get this error:
Error creating bean with name 'xxx.test.ApplicationTester': Unsatisfied dependency expressed through field 'aplicationDocumentDao';
nested exception is 0rg.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'xxx.dao.AplicationDocumentDao' available:
expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Which means is can't find the Bean of course, but i would think the #ComponentScan would pick up add the Dao's.
How do I get this tester to find all my Dao's (Which are all annotated with #Componenet) and are picked up just fine in the rest for the application.
Any ideas?
** EDIT **
here is the DAO
#Repository
#Component
public class AplicationDocumentDao extends JdbcDaoSupport {
#Autowired
public void setJT(JdbcTemplate jdbcTemplate) {
setJdbcTemplate(jdbcTemplate);
}
public List<ApplicationDocumentBean> allForOrg(int orgId) {
String sql = "SELECT * FROM ApplicationDocument WHERE organizationId = ?";
return (List<ApplicationDocumentBean>) getJdbcTemplate().query(sql, new BeanPropertyRowMapper<ApplicationDocumentBean>(ApplicationDocumentBean.class), orgId);
}
}

Add annotate to your persistence layer class, for example: #Repository or #Component,like this :
#Repository
public interface OrderMapper {}

Related

Fail to autowire dependency in test

I'd like to write a Spring integration test to make sure that #Autowired correctly puts together my classes, but fail.
The test class
#RunWith(SpringRunner.class)
#DataJpaTest
#EntityScan(basePackageClasses = {ClassUnderTest.class, SomRepository.class, SomeEntity.class})
public class ClassUnderTestIT{
#Autowired private InterfaceUnderTest cut;
#Test public void autowires() {
assertThat(cut).isNotNull();
}
}
Should test that this #Service autowires
#Service
#Transactional
public class ClassUnderTest implements InterfaceUnderTest {
private final SomeRepository repository;
#Autowired
public DefaultWatchlistDataModifier(SomeRepository repository) {
this.repository = repository;
}
}
Paying special attention to the wired dependency
#Repository
#Transactional(readOnly = true)
#Scope(value = BeanDefinition.SCOPE_PROTOTYPE)
public interface SomeRepository extends JpaRepository<SomeEntity, String> {
}
However, all I ever get is the exception
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'com.[...].InterfaceUnderTest' available:
expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations:
{#org.springframework.beans.factory.annotation.Autowired(required=true)}
Meanwhile, I have experimented with all kinds of additional annotations, such as #ComponentScan, #EnableJpaRepositories ... whatever I could dig up in the endless number of StackOverflow questions on the topic - all in vain.
Using [#DataJpaTest] will only bootstrap the JPA part of your Spring Boot application. As the unit of your test isn't part of that subset it will not be available in the application context.
Either construct it yourself and inject the dependencies or use a full blown #SpringBootTest instead.

Autowire Spring bean implementing two interfaces

Is it possible to have a Spring Bean implement 2 interfaces and be able to autowire that bean using either interface?
I have the following two interfaces:
public interface ServiceA {}
public interface ServiceB {}
Two controllers which use constructor auto-wiring to inject a different service:
#RestController
public class ControllerA {
public ControllerA(ServiceA service) {}
}
#RestController
public class ControllerB {
public ControllerB(ServiceB service) {}
}
One class that implements both the services
#Service
public class ServiceImpl implements ServiceA, ServiceB { }
I am getting a NoSuchBeanDefinitionException:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [ServiceB] found for dependency [ServiceB]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}
I'm using Spring Boot version 1.4.0
Yes it is possible, but
it is important, to create the service bean of type ServiceImpl and not as one of the service interfaces :
#Bean
ServiceImpl service() {
return new Serviceimpl();
}
Spring uses reflection on the declared bean type to find out which interfaces it implements and not on bean.getClass().
Even if this answer was voted dowen, you can be asured : it works . If it does not work for you #scarba05, your problem must be somewhere else...
You could use the #Qualifier annotation. It can be applied alongside #Autowired or #Inject at the point of injection to specify which bean you want to be injected:
#Autowired
#Qualifier("iceCream")
public void setDessert(Dessert dessert) {
this.dessert = dessert;
}
Source: Spring in Action 4th edition.
Let me answer your questions one by one:
Yes you can implement more than one interface in any spring bean.
Yes you can autowire with interface too as you did by constructor.
Your shared code working fine just check your SpringBootConfiguration class I think you are not scanning you service package or your service class is not in child package of SpringBootConfiguration class.
That's why you are facing:
NoSuchBeanDefinitionException

Spring Test + Mockito.mock - Spring fails because it tries to load the mocked bean #Autowired dependencies

I can't find out why the following simple scenario is failing: I have a Spring application with a filter that loads a Spring bean from the application context:
public class MyFilter implements Filter{
private IPermissionService permissionService;
public void init(FilterConfig filterConfig) throws ServletException {
WebApplicationContext ac = null;
try{
ac = WebApplicationContextUtils.getRequiredWebApplicationContext(filterConfig.getServletContext());
permissionService = ac.getBean(PermissionServiceImpl.class);
PermissionServiceImpl has an #Autowired attribute dataSource so in my TestNG test, I mock it in the Spring applicationContext:
#Configuration
public class MyFilterSpringTestConfig{
#Bean
public IPermissionService permissionService(){
return Mockito.mock(PermissionServiceImpl.class);
}
MyTest:
#Test
#WebAppConfiguration
#ContextConfiguration(classes=MyFilterSpringTestConfig.class)
public class MyFilterSpringTest extends BaseSpringFilterTest{
...
The problem is that on Spring initialization I get an exception complaining that PermissionServiceImpl's dataSource dependency is not satisfied. Since I wrapped it with a mock, why is it still failing? How could I fix it?
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [javax.sql.DataSource] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true), #org.springframework.beans.factory.annotation.Qualifier(value=myDataSource)}
When mocking a class using Mockito (or any other mocking framework) that class is still an instance of the original class. With that comes that it also contains all the annotations and class information with it.
So when you create a mock of the class it still detects all annotations on it and tries to full fill that. I.e. #Autowire other instances.
Either don't use auto wiring or don't mock the class but the interface (which doesn't contain that information).

Spring #ContextHierarchy with custom initializer using addActiveProfile gives NoSuchBeanDefinitionException

We are using #ContextHierarchy in our tests to enable context caching but allow some texts to customise the context. I have a problem that one test needs to activate a specific Spring profile which activates a bean which is injected back into the test.
I have a feeling this is not possible but am looking for confirmation. Logically the parent context has already been initialised, so am willing to believe Spring will have a problem re-wiring the parent context based on a profile being activated in a test that is essentially just adding a child context through #ContextHierarchy. But I couldn't find anyone describing this problem after some googling.
The base test class looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextHierarchy(
#ContextConfiguration(classes = BaseConfig.class, initializers = TestContextInitialiser.class)
)
public abstract class BaseTest extends AbstractTransactionalJUnit4SpringContextTests {
...
}
The concrete test class looks like this:
#ContextHierarchy(
#ContextConfiguration(initializers = NotificationTest.CustomInitializer.class)
)
public class NotificationTest extends BaseTest {
#Autowired
private EventsConfig eventsConfig; // bean that needs to be activated via profile
...
public static class CustomInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
#Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.getEnvironment().addActiveProfile("EVENTS_ENABLED");
}
}
}
The EventsConfig class uses #Profile...
#Component
#Profile("EVENTS_ENABLED")
public class EventsConfig {
...
}
And the error from Spring:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [xxx.EventsConfig] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I would expect that Spring would at least warn/error in this situation and explain that the parent context cannot be modified with new profiles.
Any input/guidance appreciated. Is this or something similar possible? It will be a pain to have to refactor this test to avoid use of the base class.
Thanks

Spring expected at least 1 bean which qualifies as autowire candidate for this dependency

I have a trouble with this Autowire:
#Controller
public class ChiusuraController {
#Autowired
private ChiusuraProvider chiusuraProvider;
}
with this bean:
#Service #Transactional
public class ChiusuraProvider extends ThreadProvider {
public void run() {}
}
that extends
public abstract class ThreadProvider extends Thread implements InitializingBean, Runnable, DisposableBean {
...
}
I get this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'chiusuraController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.cinebot.service.ChiusuraProvider com.cinebot.web.controller.ChiusuraController.chiusuraProvider; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.cinebot.service.ChiusuraProvider] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
I saw that I did not get this error if I remove extends ThreadProvider of autowired class, but I really need ThreadProvider abstract class.
If there is an interface anywhere in the ThreadProvider hierarchy try putting the name of the Interface as the type of your service provider, eg. if you have say this structure:
public class ThreadProvider implements CustomInterface{
...
}
Then in your controller try this:
#Controller
public class ChiusuraController {
#Autowired
private CustomInterface chiusuraProvider;
}
The reason why this is happening is, in your first case when you DID NOT have ChiusuraProvider extend ThreadProvider Spring probably was underlying creating a CGLIB based proxy for you(to handle the #Transaction).
When you DID extend from ThreadProvider assuming that ThreadProvider extends some interface, Spring in that case creates a Java Dynamic Proxy based Proxy, which would appear to be an implementation of that interface instead of being of ChisuraProvider type.
If you absolutely need to use ChisuraProvider you can try AspectJ as an alternative or force CGLIB based proxy in the case with ThreadProvider also this way:
<aop:aspectj-autoproxy proxy-target-class="true"/>
Here is some more reference on this from the Spring Reference site: http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/classic-aop-spring.html#classic-aop-pfb
You should put this line in your application context:
<context:component-scan base-package="com.cinebot.service" />
Read more about Automatically detecting classes and registering bean definitions in documentation.

Resources