我正在使用JUnit测试Spring的组件,抛出错误:
org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'wsVehicleService' is defined
这是我的测试课:
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();
}
}
}
这是将要测试的课程:
@Component
public class WsVehicleService {
public List<HistoryAlarmInfo> getHistoryAlarmInfo(String requestJson) {
try {
return getHistoryAlarmInfoImpl(requestJson);
} catch (Exception e) {
log.error(e);
return null;
}
}
}
当JUnit运行getBean时,抛出错误:
No bean named 'wsVehicleService' is defined
。
哪里出了问题?我能做些什么来纠正它?
我尝试过的:
添加
@ComponentScan("com.zw.ws.*")
来扫描 WsVehicleService 类。
这是日志:
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:这不是 XML 配置,所有 bean 都使用自动扫描。
“没有定义名为‘xxx’的 bean”会在以下情况下抛出:
既然你没有改变bean的默认名称,那么一定是bean没有正确加载。
您需要指示在运行测试时要扫描和加载组件的位置(xml 配置或 @Configuration 类)。 我将创建一个配置类,然后在 ContextConfiguration 注释中添加这个新的配置类(如果您愿意,也可以使用 xml)。
@Configuration
@ComponentScan(basePackages = {"com.zw.ws"})
public class AppTestConfig {}
你的测试课:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={AppTestConfig.class})
public class WsVehicleServiceTest {
...
}
您还可以使用
@Autowire
您的服务进行注释,并让 Spring 完成接线工作。
1)第一个解决方案:
@ContextConfiguration
初始化Spring上下文,默认情况下在与单元测试相同的包中查找Spring XML文件,文件名与类相同,后缀为“-context.xml”
尝试在
com.mycompany.annotation
包中添加 WsVehicleServiceTest-context.xml 文件。
<?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 测试类 ("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();
}
}
}
注意:如果您想使用
@ContextConfiguration("classpath:/*.xml")
,请确保放置
<bean id="wsVehicleService"
class="com.mycompany.annotation.WsVehicleService">
</bean>
在您的任何一个 *.xml 文件中
2)第二种解决方案:
确保将
<context:annotation-config />
放入 xml 文件中。在这里,您不需要在 xml 文件中声明 wsVehicleService bean。
使用
@Autowired
上的 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)第三种解决方案:
您已经提到,您没有使用任何 xml 配置文件,并且您的异常告诉
org.springframework.beans.factory.NoSuchBeanDefinitionException
您的 WsVehicleService 可能不存在于上下文中的一个原因是它可能定义在 Spring 未扫描的包中。
确保您的 WsVehicleService 存在于
@ComponentScan("com.mycompany.annotation")
包中。
1)带有注解的应用程序配置类@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) 您的服务等级
package com.mycompany.annotation;
import org.springframework.stereotype.Component;
@Component
public class WsVehicleService {
public String sayHi(){
return "HI !!!!!!!!!!";
}
}
3)Junit测试类
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();
}
}
}
输出:
HI !!!!!!!!!!
换线
WsVehicleService vehicleService = (WsVehicleService) ctx.getBean(WsVehicleService .class);
或
@Component("wsVehicleService")
public class WsVehicleService{
//..
}
Spring注解代码
//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"})
根据您的基础包进行更改
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( );
}
}
如果我们使用基于
Component
的注释,我们必须在该 configLocation .xml
中提供包路径,如下所示
<context:component-scan base-package="org.example.javaconfig"/>
解决了我的问题