Reputation: 38681
I am using JUnit to test Component of Spring,throws error:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'wsVehicleService' is defined
This is my test class:
package com.zw.ws.service.impl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/*.xml")
public class WsVehicleServiceTest {
@Autowired
ApplicationContext ctx;
@Test
public void getHistoryAlarmInfo() throws Exception {
try {
String requestJson = "\"{\"VEHICLEID\":\"cae21196-cb66-4256-88a6-7cdfb23e2c78\",\"STARTTIME\":1476115200,\"ENDTIME\":1476201599,\"TYPE\":1}\"";
WsVehicleService vehicleService = (WsVehicleService) ctx.getBean("wsVehicleService");
vehicleService.getHistoryAlarmInfoImpl(requestJson);
} catch (BeansException e) {
e.printStackTrace();
}
}
}
This is the class will be tested:
@Component
public class WsVehicleService {
public List<HistoryAlarmInfo> getHistoryAlarmInfo(String requestJson) {
try {
return getHistoryAlarmInfoImpl(requestJson);
} catch (Exception e) {
log.error(e);
return null;
}
}
}
When JUnit run to getBean,throws error:No bean named 'wsVehicleService' is defined
.
Where is going wrong?What could I do to make it right?
What I having tried:
add @ComponentScan("com.zw.ws.*")
to scan the WsVehicleService class.
This is the log:
12:53:11.098]-[main]-[org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener]-{After test method: context [DefaultTestContext@58783f6c testClass = WsVehicleServiceTest, testInstance = com.zw.ws.service.impl.WsVehicleServiceTest@7577b641, testMethod = getHistoryAlarmInfo@WsVehicleServiceTest, testException = org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'wsVehicleService' is defined, mergedContextConfiguration = [MergedContextConfiguration@3a7b503d testClass = WsVehicleServiceTest, locations = '{classpath:/*.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null], method annotated with @DirtiesContext [false] with mode [null].}
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'wsVehicleService' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:698)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1175)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:284)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1054)
at com.zw.ws.service.impl.WsVehicleServiceTest.getHistoryAlarmInfo(WsVehicleServiceTest.java:27)
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 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
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:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
at org.junit.runner.JUnitCore.run(JUnitCore.java:160)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:117)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:253)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:84)
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)
12:53:11.107]-[main]-[org.springframework.test.context.support.AbstractDirtiesContextTestExecutionListener]-{After test class: context [DefaultTestContext@58783f6c testClass = WsVehicleServiceTest, testInstance = [null], testMethod = [null], testException = [null], mergedContextConfiguration = [MergedContextConfiguration@3a7b503d testClass = WsVehicleServiceTest, locations = '{classpath:/*.xml}', classes = '{}', contextInitializerClasses = '[]', activeProfiles = '{}', propertySourceLocations = '{}', propertySourceProperties = '{}', contextLoader = 'org.springframework.test.context.support.DelegatingSmartContextLoader', parent = [null]]], class annotated with @DirtiesContext [false] with mode [null].}
PS:This is no XML configuration,all beans are using autoscan.
Upvotes: 4
Views: 79714
Reputation: 1
i have make same mistake and just find some simple solution for this issue while calling the getBean method in main class just include the object name which are defined in XML config.
Pass the object Name while calling the getBean;
Upvotes: -1
Reputation: 2672
If We are using Component
based annotation we have to provide the package path as follows in that configLocation .xml
as
<context:component-scan base-package="org.example.javaconfig"/>
which solved my problem
Upvotes: 0
Reputation: 95
Spring Annotation code
//main class
//@Import(value=AppConfig.class)
public class AppAnno {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new
AnnotationConfigApplicationContext(AppConfig.class);
TodayDate date = ctx.getBean("todayDate",TodayDate.class);
System.out.println(date.getTodyDate());
}
}
@Configuration
@ComponentScan(basePackages={"com.cb.service.anno","com.cb.dao.anno"})
change it according to your basepackage
public class AppConfig {
@Bean
public Date date(){
return new Date();
}
}
import java.util.Date;
import javax.inject.Named;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
@Named("todayDate")//you have to add inject jar to your build path
public class TodayDate {
@Autowired
Date date;
public String getTodyDate(){
return date.toString( );
}
}
Upvotes: 0
Reputation: 2137
1)First Solution:
@ContextConfiguration
initializes the Spring context and by default looks for a Spring XML file in the same package as the unit test with the file name the same as the class with '-context.xml' as a suffix
Try adding the WsVehicleServiceTest-context.xml file in com.mycompany.annotation
package.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="wsVehicleService"
class="com.mycompany.annotation.WsVehicleService">
</bean>
</beans>
Junit test class after removing ("classpath:/*.xml"):
package com.mycompany.annotation;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class WsVehicleServiceTest {
@Autowired
ApplicationContext ctx;
@Test
public void getHistoryAlarmInfo() throws Exception {
try {
WsVehicleService vehicleService = (WsVehicleService) ctx
.getBean("wsVehicleService");
String hi = vehicleService.sayHi();
System.out.println(hi);
} catch (BeansException e) {
e.printStackTrace();
}
}
}
Note: If you want to use @ContextConfiguration("classpath:/*.xml")
make sure you put
<bean id="wsVehicleService"
class="com.mycompany.annotation.WsVehicleService">
</bean>
in any one of your *.xml file
2) Second Solution:
Make sure you put <context:annotation-config />
in your xml file. Here you do not need to declare the wsVehicleService bean in your xml file.
Modify your test class by using @Autowired
on WsVehicleService
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:/*.xml")
public class WsVehicleServiceTest {
@Autowired
ApplicationContext ctx;
@Autowired
WsVehicleService wsVehicleService;
@Test
public void getHistoryAlarmInfo() throws Exception {
try {
String hi = wsVehicleService.sayHi();
System.out.println(hi);
} catch (BeansException e) {
e.printStackTrace();
}
}
}
3) Third solution:
You have mentioned, you do not use any xml configuration files and your exception tells org.springframework.beans.factory.NoSuchBeanDefinitionException
One reason your WsVehicleService may not exist in the context – is that it may be defined in a package that is not scanned by Spring.
Make sure your WsVehicleService exist in @ComponentScan("com.mycompany.annotation")
package.
1) Application configuration class with annotation @Configuration
package com.mycompany.annotation;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.mycompany.annotation")
public class AppConfig {
}
2) Your service class
package com.mycompany.annotation;
import org.springframework.stereotype.Component;
@Component
public class WsVehicleService {
public String sayHi(){
return "HI !!!!!!!!!!";
}
}
3)Junit test class
package com.mycompany.annotation;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = AppConfig.class)
public class WsVehicleServiceTest {
@Autowired
ApplicationContext ctx;
@Test
public void getHistoryAlarmInfo() throws Exception {
try {
WsVehicleService vehicleService = (WsVehicleService) ctx
.getBean("wsVehicleService");
String hi = vehicleService.sayHi();
System.out.println(hi);
} catch (BeansException e) {
e.printStackTrace();
}
}
}
OUTPUT:
HI !!!!!!!!!!
For more info you can refer this and this
More reference for causes and possible solution for NoSuchBeanDefinitionException
Upvotes: 6
Reputation: 2340
"No bean named 'xxx' is defined" is thrown when:
Since you haven't changed the default name of the bean, then must be that the bean isn't properly loaded.
You need to indicate where are your components to be scanned (xml config or @Configuration class) and be loaded when run your tests. I would create a config class and then add this new config class in the ContextConfiguration annotation (or use xml if you prefer).
@Configuration
@ComponentScan(basePackages = {"com.zw.ws"})
public class AppTestConfig {}
Your test class then:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={AppTestConfig.class})
public class WsVehicleServiceTest {
...
}
You can also anotate with @Autowire
your service and let Spring do the wiring work.
Upvotes: 9
Reputation: 11017
Change line
WsVehicleService vehicleService = (WsVehicleService) ctx.getBean(WsVehicleService .class);
or
@Component("wsVehicleService")
public class WsVehicleService{
//..
}
Upvotes: 6