I have spent numerous hours of setting this up. I am trying to setup a JUnit to test a simple NodeEntity class and a Repository. I am also using Gradle (not Maven -- to be Gradle seems cleaner then the Maven pom.xml). Also, I am using the Java Configuration class.
build.gradle:
apply plugin:'java'
apply plugin:'idea'
project.ext {
springVersion = "4.0.3.RELEASE"
neo4jVersion = "2.0.1.RELEASE"
springDataGraphVersion = "3.0.1.RELEASE"
sourceCompatibility = 1.7
version = '1.0'
}
configurations {
runtime
testCompile
}
repositories {
mavenCentral()
mavenLocal()
maven {
url "http://m2.neo4j.org/content/repositories/releases/"
}
}
dependencies {
compile 'org.slf4j:slf4j-api:1.7.5'
compile "org.springframework:spring-context:${springVersion}"
compile "org.neo4j:neo4j:${neo4jVersion}"
// Provides Repository based Object <-> Graph Mapping
compile "org.springframework.data:spring-data-neo4j:${springDataGraphVersion}"
compile "javax.validation:validation-api:1.0.0.GA"
testCompile 'junit:junit-dep:4.11'
testCompile "org.springframework:spring-test:${springVersion}"
testCompile 'org.hamcrest:hamcrest-all:1.3'
// Access to Neo4j testing facilities: TestGraphDatabaseFactory
testCompile "org.neo4j:neo4j-kernel:${neo4jVersion}:tests#jar"
testRuntime 'org.slf4j:slf4j-simple:1.7.5'
}
// Generate wrapper for Gradle
task wrapper(type: Wrapper) {
gradleVersion = '1.11'
}
Test Class
import domains.BaseClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import repos.BaseClassRepository;
import static org.junit.Assert.assertEquals;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes={AppConfigTest.class})
public class TestBaseClass {
#Autowired
private BaseClassRepository baseClassRepository;
#Autowired
private GraphDatabaseService graphDb;
#Transactional
#Test
public void shouldCreateNode () {
BaseClass testClass = null;
try (Transaction tx = graphDb.beginTx()) {
testClass = new BaseClass();
testClass.setName("Archer");
baseClassRepository.save(testClass);
tx.success();
} catch (Exception e) {
System.err.println(e.getMessage());
}
BaseClass testClass1 = baseClassRepository.findByName("Archer");
assertEquals(testClass1.getName(), "Archer");
System.out.println(testClass.getName());
}
}
Stack Trace:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:101)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:319)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:212)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:232)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:175)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:80)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:47)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:69)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:103)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:355)
at org.gradle.internal.concurrent.DefaultExecutorFactory$StoppableExecutorImpl$1.run(DefaultExecutorFactory.java:66)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baseClassRepository': Cannot resolve reference to bean 'neo4jTemplate' while setting bean property 'neo4jTemplate'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'neo4jTemplate' is defined
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:336)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1456)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1197)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:684)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:121)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:100)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:250)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContextInternal(CacheAwareContextLoaderDelegate.java:64)
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:91)
... 44 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'neo4jTemplate' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:641)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1159)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:282)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
... 62 more
Also, for some reason the shouldCreateNode() function runs twice for the test. Not sure why either. =(
AppConfigTest Configuration
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.test.TestGraphDatabaseFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.config.EnableNeo4jRepositories;
import org.springframework.data.neo4j.config.Neo4jConfiguration;
#Configuration
#ComponentScan(basePackages = "domains")
#EnableNeo4jRepositories(basePackages = "repos")
public class AppConfigTest extends Neo4jConfiguration {
public AppConfigTest () {
setBasePackage("domains");
}
#Bean
public GraphDatabaseService graphDatabaseService() {
return new TestGraphDatabaseFactory().newImpermanentDatabase();
}
}
I finally got a working solution.
For my AppConfigTest class. I needed to extend it from Neo4jConfiguration for it to #Autowire the Neo4jTemplate. I thought this was only for the real application.
Secondly, after I fixed I was getting a error similar to spring-data-neo4j#161 on github. That error points you to the Neo4j Blog's post: Spring-Data-Neo4j Progress Update SDN 3 which I was missing the setBasePackages() function in my constructor (see updated code in question).
Third, seems #NodeEntity objects can't contain vars in the constructor either. So removed that from my test when creating my base class.
The compiler complains about
No bean named 'neo4jTemplate' is defined
which is in your test class TestBaseClass. So in order to inject the dependency of this class, you need to add the Neo4jTemplate bean in the configuration class:
public class AppConfigTest {
#Bean
public GraphDatabaseService graphDatabaseService() {
return new TestGraphDatabaseFactory().newImpermanentDatabase();
}
#Bean
public Neo4jTemplate neo4jBean() {
return new Neo4jTemplate(graphDatabaseService());
}
}
Note that Neo4jTemplate class in latest Spring version has the constructor argument dependency on GraphDatabaseService class. So you can do the above to do bean injection via constructor argument.
Related
I am new to Mockito , I am trying to write Unit Tests for Main Class facing some issue not able to instantiate the bean. Please anyone help me to fix that issue. If anyone give me suggestion how to approach to write the unit tests in mockito for below class.
Main class
import com.ab.obs.spring.ObsSpringBootApplicationForCloud;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import com.ab.obs.config.EncryptDecryptUtilConfig;
import com.ab.csl.retail.core.config.HikariDataSourceConfig;
import org.springframework.context.annotation.Import;
#Import({EncryptDecryptUtilConfig.class, HikariDataSourceConfig.class})
#SpringBootApplication
#EnableAspectJAutoProxy
public class ObsDocumentApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
ObsSpringBootApplicationForCloud.initBase(application, "csl-svc-obs-test");
return application;
}
public static void main(String[] args) {
SpringApplicationBuilder application = new SpringApplicationBuilder();
ObsSpringBootApplicationForCloud.initBase(application, "csl-svc-obs-test");
application.sources(ObsDocumentApplication.class)
.run(args);
}
}
Test Class here:
import com.ab.obs.spring.ObsSpringBootApplicationForCloud;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.springframework.boot.builder.SpringApplicationBuilder;
import static org.powermock.api.mockito.PowerMockito.*;
#RunWith(PowerMockRunner.class)
#PrepareForTest({ObsDocumentApplication.class, ObsSpringBootApplicationForCloud.class})
public class ObsDocumentApplicationTest {
#Mock
private SpringApplicationBuilder applicationBuilder;
#Before
public void setUp() throws Exception{
PowerMockito.spy(ObsDocumentApplication.class);
PowerMockito.spy(ObsSpringBootApplicationForCloud.class);
applicationBuilder = mock(SpringApplicationBuilder.class);
}
#Test
public void testMainClass() {
ObsDocumentApplication.main(new String[] {});
}
}
Error log:
java.lang.IllegalArgumentException: Cannot instantiate interface org.springframework.context.ApplicationListener : org.springframework.cloud.function.compiler.config.FunctionProxyApplicationListener
at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:467)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:449)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:442)
at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:285)
at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:264)
at org.springframework.boot.builder.SpringApplicationBuilder.createSpringApplication(SpringApplicationBuilder.java:109)
at org.springframework.boot.builder.SpringApplicationBuilder.<init>(SpringApplicationBuilder.java:97)
at com.sc.obs.ObsDocumentApplication.main(ObsDocumentApplication.java:25)
at com.sc.obs.ObsDocumentApplicationTest.testMainClass(ObsDocumentApplicationTest.java:31)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:89)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:97)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:87)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:50)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:34)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:44)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.cloud.function.compiler.config.FunctionProxyApplicationListener]: Constructor threw exception; nested exception is java.lang.ClassCastException: class com.sun.tools.javac.api.JavacTool
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:225)
at org.springframework.boot.SpringApplication.createSpringFactoriesInstances(SpringApplication.java:463)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:449)
at org.springframework.boot.SpringApplication.getSpringFactoriesInstances(SpringApplication.java:442)
at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:285)
at org.springframework.boot.SpringApplication.<init>(SpringApplication.java:264)
at org.springframework.boot.builder.SpringApplicationBuilder.createSpringApplication(SpringApplicationBuilder.java:109)
at org.springframework.boot.builder.SpringApplicationBuilder.<init>(SpringApplicationBuilder.java:97)
at com.sc.obs.ObsDocumentApplication.main(ObsDocumentApplication.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.powermock.api.mockito.invocation.InvocationFactory$1.call(InvocationFactory.java:55)
at org.mockito.internal.invocation.RealMethod$FromCallable$1.call(RealMethod.java:40)
at org.mockito.internal.invocation.RealMethod$FromBehavior.invoke(RealMethod.java:62)
at org.mockito.internal.invocation.InterceptedInvocation.callRealMethod(InterceptedInvocation.java:141)
at org.mockito.internal.stubbing.answers.CallsRealMethods.answer(CallsRealMethods.java:44)
at org.mockito.Answers.answer(Answers.java:98)
at org.mockito.internal.handler.MockHandlerImpl.handle(MockHandlerImpl.java:106)
at org.mockito.internal.handler.NullResultGuardian.handle(NullResultGuardian.java:29)
at org.mockito.internal.handler.InvocationNotifierHandler.handle(InvocationNotifierHandler.java:33)
at org.powermock.api.mockito.invocation.MockHandlerAdaptor.performIntercept(MockHandlerAdaptor.java:64)
at org.powermock.api.mockito.invocation.MockitoMethodInvocationControl.invoke(MockitoMethodInvocationControl.java:94)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:186)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:168)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:145)
at com.sc.obs.ObsDocumentApplication.main(ObsDocumentApplication.java)
at com.sc.obs.ObsDocumentApplicationTest.testMainClass(ObsDocumentApplicationTest.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
There's little value in writing a unit test for your Spring Boot entry-point class ObsDocumentApplication as you end up with almost an exact copy of your implementation.
Such tests can only verify that your mocking setup matches your implementation. Any change to your implementation will most probably fail the unit test as the stubbing setup needs to be adjusted.
A better approach is to write an integration test that makes sure your Spring ApplicationContext can launch (which will implicitly verify your ObsDocumentApplication).
You can use the #SpringBootTest annotation for this purpose.
I am using SpringBoot and I have a DataJpaTest, but when I run the Test class, I get this StackTrace:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:47)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:237)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'restTemplate' defined in br.com.mobtrack.api.MobTrackApplication: Unsatisfied dependency expressed through method 'restTemplate' parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.web.client.RestTemplateBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:749)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:467)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1134)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1028)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:759)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:761)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:371)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315)
at org.springframework.boot.test.context.SpringBootContextLoader.loadContext(SpringBootContextLoader.java:111)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 28 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.web.client.RestTemplateBuilder' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1474)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1102)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064)
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:835)
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:741)
I think this happens because I have a RestTemplate bean inside my Application class like this:
#SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
This is my Test Class:
#RunWith(SpringRunner.class)
#DataJpaTest
public class CityRepositoryTest {
#Autowired
private TestEntityManager entityManager;
#Autowired
private CityRepository cityRepository;
private City city;
#Before
public void init() {
city = new City();
city.setName("New York");
city.setImage("http://www.mockimage.com");
}
#Test
public void findByNameShouldReturnCity() throws Exception {
this.entityManager.persist(city);
Optional<City> hasCity = this.cityRepository.findByNameIgnoreCase("New York");
city = hasCity.get();
assertThat(city.getId()).isNotNull();
assertThat(city.getName()).isEqualTo("New York");
assertThat(city.getImage()).isEqualTo("http://www.mockimage.com");
}
#Test
public void findByNameStartingWithShouldReturnCity() throws Exception {
this.entityManager.persist(city);
Optional<City> hasCity = this.cityRepository.findByNameStartingWithIgnoreCase("New");
city = hasCity.get();
assertThat(city.getId()).isNotNull();
assertThat(city.getName()).isEqualTo("New York");
assertThat(city.getImage()).isEqualTo("http://www.mockimage.com");
}
#Test
public void findByNameWhenNoCityShouldReturnFalse() throws Exception {
this.entityManager.persist(city);
Optional<City> hasCity = this.cityRepository.findByNameStartingWithIgnoreCase("Ohaio");
assertThat(hasCity.isPresent()).isFalse();
}
}
Any help is welcome,Thanks a lot!
I didn't like the other solution as I did want my application to use the spring provided RestTemplateBuilder since it provides some default message converters and other functionality I needed when running my app.
However I found 2 ways to alter my test to get my DataJpaTest's to run, not sure which is best:
Method One - provide a mock RestTemplate in your test.
#RunWith(SpringRunner.class)
#DataJpaTest
public class SomeTest {
#MockBean
private RestTemplate restTemplate;
Method Two - add AutoConfigureWebClient annotation so spring will wire the RestTemplateBuilder
#RunWith(SpringRunner.class)
#DataJpaTest
#AutoConfigureWebClient
public class SomeTest {
With both ways I could keep my existing configured rest template in my application class:
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
As the error is clearly saying - there is no qualifying bean of type RestTemplateBuilder being available for use of RestTemplate bean building.
The bean for RestTempalteBuilder is injected into context by the spring boot starter for web. There is generally no need to declare a RestTemplateBuilder bean into the context as it is already provided by the spring-boot auto-configuration. If the project is a spring-boot application this will work out of box as intended.
If required, one can customise it by creating a new one in the application configuration.Something like below:
#Bean
public RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder()
.basicAuthorization("abc", "password");
}
#Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
And if no real reason to customise it, you could rather have a simpler bean definition for RestTemplate as below:
#Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
Dear StackOverflow experts.
We are solving interesting issue in current sprint and our understanding of Spring workflow doesn't allow us to find a solution.
So we ask you to share your thought on next problem:
We need to import class from a library which we can not modify right now.
The thing is that the class we need to import has an Autowired dependency of a class which implements "ApplicationListener".
We won't use this dependency in our code (it is used in methods we won't call).
We trying to set all unused dependencies to null.
But when we set this class to null we get an exception:
Caused by: java.lang.IllegalArgumentException: Delegate listener must not be null
Obviously, we don't want to instantiate ApplicationListener class in our application.
To reproduce our situation we create a simple unit tests:
Application configuration:
#Configuration
public class TestApplicationConfiguration {
#Bean
public ApplicationListener<ContextRefreshedEvent> applicationListener() {
return null;
}
}
Test class:
#ContextConfiguration(classes = TestApplicationConfiguration.class)
public class ConfigurationManagerTests extends AbstractTestNGSpringContextTests {
#Autowired
private ApplicationListener<ContextRefreshedEvent> applicationListener;
#Test
public void dummyTest() {
Assert.assertNull(applicationListener);
}
}
Full stacktrace of the exception listed below.
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.testng.AbstractTestNGSpringContextTests.springTestContextPrepareTestInstance(AbstractTestNGSpringContextTests.java:149)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:86)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:514)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:215)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:142)
at org.testng.internal.TestMethodWorker.invokeBeforeClassMethods(TestMethodWorker.java:178)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:108)
at org.testng.TestRunner.privateRun(TestRunner.java:782)
at org.testng.TestRunner.run(TestRunner.java:632)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:366)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:361)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:319)
at org.testng.SuiteRunner.run(SuiteRunner.java:268)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1244)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1169)
at org.testng.TestNG.run(TestNG.java:1064)
at org.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:72)
at org.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:124)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
Caused by: java.lang.IllegalArgumentException: Delegate listener must not be null
at org.springframework.util.Assert.notNull(Assert.java:115)
at org.springframework.context.event.GenericApplicationListenerAdapter.<init>(GenericApplicationListenerAdapter.java:48)
at org.springframework.context.event.AbstractApplicationEventMulticaster.supportsEvent(AbstractApplicationEventMulticaster.java:280)
at org.springframework.context.event.AbstractApplicationEventMulticaster.retrieveApplicationListeners(AbstractApplicationEventMulticaster.java:229)
at org.springframework.context.event.AbstractApplicationEventMulticaster.getApplicationListeners(AbstractApplicationEventMulticaster.java:185)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:382)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:336)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:877)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 33 more
Thanks.
Looks like Spring itself doesn't allow that bean to be null, so why not just create a dummy one which doesn't do anything?
#Bean
public ApplicationListener<ContextRefreshedEvent> applicationListener() {
return new ApplicationListener<ContextRefreshedEvent>() {
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// Do nothing
}
};
}
Below is my Bean configuration code, but the configuration doesn't pass the test as it says it failed to load ApplicationContext. Is there something I'm doing wrong? I added #Autowire to methods of each class that's needed (except for interface method), but I still have no idea why it's not loading
package soundsystems;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class CDPlayerConfig
{
#Bean
public CompactDisc sgtPeppers()
{
return new SgtPeppers();
}
#Bean(name = "SgtPepperPlayer")
public CDPlayer cdPlayer()
{
return new CDPlayer(sgtPeppers());
}
#Bean(name = "AnyCDPlayer")
public CDPlayer cdPlayer(CompactDisc cd)
{
return new CDPlayer(cd);
}
#Bean
public BlankDisc reallyBlankDisc()
{
return new BlankDisc();
}
#Bean
public BlankDisc blankDisc()
{
BlankDisc bd = new BlankDisc();
String title = "Sgt. Pepper's Lonely Hearts Club Band";
String artist = "The Beatles";
List<String> tracks = new ArrayList<String>();
tracks.add("Sgt. Pepper's Lonely Hearts Club Band");
tracks.add("With a Little Help from My Friends");
tracks.add("Lucy in the Sky with Diamonds");
tracks.add("Getting Better");
tracks.add("Fixing a Hole");
bd.setTitle(title);
bd.setArtist(artist);
bd.setTracks(tracks);
return bd;
}
#Bean
public Discography beatlesDiscography()
{
Discography dg = new Discography();
String artist = "The Beatles";
CompactDisc SgtPeppers = new SgtPeppers();
CompactDisc WhiteAlbum = new WhiteAlbum();
CompactDisc HardDaysNight = new HardDaysNight();
CompactDisc Revolver = new Revolver();
List<CompactDisc> cds = new ArrayList<CompactDisc>();
cds.add(SgtPeppers);
cds.add(WhiteAlbum);
cds.add(HardDaysNight);
cds.add(Revolver);
dg.setArtist(artist);
dg.setCDs(cds);
return dg;
}
}
package soundsystems;
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.SystemOutRule;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = CDPlayerConfig.class)
public class CDPlayerTest
{
#Rule
public final SystemOutRule log = new SystemOutRule().enableLog();
#Autowired
private CompactDisc cd;
#Autowired
private MediaPlayer player;
#Test
public void cdShouldNotBeNull()
{
assertNotNull(cd);
}
#Test
public void play()
{
player.play();
assertEquals("Playing Sgt. Pepper's Lonely Hearts Club Band" + " by The Beatles\n", log.getLog());
}
}
Thanks for having a look.
edit: Error
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:249)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
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)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'AnyCDPlayer': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void soundsystems.CDPlayer.setCompactDisc(soundsystems.CompactDisc); nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [soundsystems.CompactDisc] is defined: expected single matching bean but found 3: blankDisc,sgtPeppers,reallyBlankDisc
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:125)
at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:109)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:261)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 25 more
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire method: public void soundsystems.CDPlayer.setCompactDisc(soundsystems.CompactDisc); nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [soundsystems.CompactDisc] is defined: expected single matching bean but found 3: blankDisc,sgtPeppers,reallyBlankDisc
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:661)
at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
... 41 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [soundsystems.CompactDisc] is defined: expected single matching bean but found 3: blankDisc,sgtPeppers,reallyBlankDisc
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1126)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:618)
... 43 more
I believe that Spring's #Autowired default mode is by type. It means that Spring will try to autowire bean by interface type, btw you have 3 beans with same interface and Spring got confused which one to choose. If you want to achieve autowiring by name you should use #Qualifier: #Qualifier("beanname")
The error is quite clear:
Could not autowire method: public void soundsystems.CDPlayer.setCompactDisc(soundsystems.CompactDisc);
nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException:
No qualifying bean of type [soundsystems.CompactDisc] is defined:
expected single matching bean but found 3: blankDisc,sgtPeppers,reallyBlankDisc
You annotated you setCompactDisc() method in CDPlayer with #Autowired, so Spring tries to call it with a bean of type CompactDisc, but it has 3 of them, and thus can't decide which one to inject. Don't annotate this method with Autowired. Or even better, remove that method, since the CompactDisc is already initialized by the constructor.
I am migrating away from XML config for Spring context configuration. Instead when I try to use the functionally equivalent #EnableTransactionManagement on a Spring 4.0.3.RELEASE Java Configuration, my Spring context fails to instantiate with the following exception:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.CacheAwareContextLoaderDelegate.loadContext(CacheAwareContextLoaderDelegate.java:99)
at org.springframework.test.context.DefaultTestContext.getApplicationContext(DefaultTestContext.java:101)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:75)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:319)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:212)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:289)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:291)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:232)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:175)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:236)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:134)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:113)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:103)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:74)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'baseMySQLTest.TestConfig': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.transaction.config.internalTransactionAdvisor' defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.transaction.intercep...skipping...
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1558)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
... 45 more
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: Factory method [public org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration.transactionAdvisor()] threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionInterceptor' defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'transactionManager' is required
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:188)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:586)
... 62 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionInterceptor' defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Property 'transactionManager' is required
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1553)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:324)
at org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$83a12634.transactionInterceptor()
at org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration.transactionAdvisor(ProxyTransactionManagementConfiguration.java:45)
at org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$83a12634.CGLIB$transactionAdvisor$0()
at org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$83a12634$$FastClassBySpringCGLIB$$cc829ae.invoke()
at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
at org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$83a12634.transactionAdvisor()
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
... 63 more
Caused by: java.lang.IllegalArgumentException: Property 'transactionManager' is required
at org.springframework.transaction.interceptor.TransactionAspectSupport.afterPropertiesSet(TransactionAspectSupport.java:195)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1612)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1549)
... 82 more
This happens to obtain in a unit test, but when it works here, I can use it in production code.
Here is my unit test base class where the Spring wiring occurs:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {PropertyPlaceholderConfigurer.class, BaseMySQLTest.TestConfig.class})
public class BaseMySQLTest extends AbstractTransactionalJUnit4SpringContextTests {
#Configuration
#Import(DaoConfig.class)
#PropertySource("classpath:/jdbc.properties")
#EnableTransactionManagement
public static class TestConfig {
#Bean
public PlatformTransactionManager providesTransactionManager(ListableBeanFactory beanFactory) {
return new DataSourceTransactionManager(beanFactory.getBean(DataSource.class));
}
}
}
and here is a subclass that uses this base class and config:
public class UserDaoImplTest extends BaseMySQLTest {
#Autowired
private UserDao userDao;
#Test
public void testById() throws Exception {
jdbcTemplate.execute("insert into users (email) values ('bob#example.com')");
...
}
}
As one can see, my Spring TestConfig has a transaction manager bean defined, which according to the Javadoc
http://docs.spring.io/spring/docs/3.1.x/javadoc-api/org/springframework/transaction/annotation/EnableTransactionManagement.html
means I do not have to name the bean (though I have named it in an attempt to get this to work). In fact, the Spring context is behaving as if configured with XML config in the face of no bean explicitly named "transactionManager".
What is my Java Config missing such that the Spring context cannot use this transaction manager bean to satisfy its requirements at instantiation time?
Thank you for any helpful observations.
EDIT:
(I'm not sure where this edit should go, so I try here. ae6rt)
Here is the new test class, which results in the same error as the original work:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {BaseMySQLTest.TestConfig.class})
public class BaseMySQLTest extends AbstractTransactionalJUnit4SpringContextTests {
protected int lastInsertId() {
return jdbcTemplate.queryForInt("select LAST_INSERT_ID()");
}
#Autowired
private UserDao userDao;
#Test
public void testById() throws Exception {
jdbcTemplate.execute("insert into mgdb.users (email) values ('bob#example.com')");
int userId = lastInsertId();
Optional xoomUserOptional = userDao.byId(userId);
assertThat(xoomUserOptional.isPresent(), equalTo(true));
XoomUser user = xoomUserOptional.get();
assertThat(user.getEmailAddress(), equalTo("bob#example.com"));
}
#Configuration
#Import(DaoConfig.class)
#PropertySource("classpath:/jdbc.properties")
#EnableTransactionManagement
public static class TestConfig {
#Bean
public PlatformTransactionManager providesTransactionManager(ListableBeanFactory beanFactory) {
return new DataSourceTransactionManager(beanFactory.getBean(DataSource.class));
}
}
}
I didn't actualy need the property config here
#ContextConfiguration(classes = {BaseMySQLTest.TestConfig.class})
so I removed it. Hope this meets the spirit of this round.
Looks like the only change should be to name your transaction manager bean name to "transactionManager":
public static class TestConfig {
#Autowired
private DataSource datasource;
#Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(datasource);
}
}
EDIT :
Can you try these additional things:
.1. Remove PropertyPlaceHolderConfigurer from here.. #ContextConfiguration(classes = {PropertyPlaceholderConfigurer.class, BaseMySQLTest.TestConfig.class}), that is not how PropertyPlaceholderConfigurer is used, you have to do it this way:
#Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
PropertySourcesPlaceholderConfigurer placeholderConfigurer = new PropertySourcesPlaceholderConfigurer();
ClassPathResource resource = new ClassPathResource("/META-INF/spring/database.properties");
placeholderConfigurer.setLocation(resource);
return placeholderConfigurer;
}
Also, just for test, can you move your actual test to the base class also and see if one of these configuration works out for you. I tested in my own machine and it seems to work nicely with Spring 4.0.2+.