为什么Spring找不到我的Bean?

4

我创建了一个接口和一个类:

public interface UserService {
    List<User> listAll();
}

@Transactional
public class DefaultUserService implements UserService {
    private String tableName;
    public List<User> listAll() { someDao.listAllFromTable(tableName); }
    public void setTableName(String tableName) { this.tableName = tableName; }
}

同时,在我的应用程序上下文xml文件context.xml中,我定义了:

<bean id="userService" class="mypackage.DefaultUserService">
    <property name="tableName" value="myusers" />
</bean>

接下来,我想测试DefaultUserService

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:context-test.xml"})
@TransactionConfiguration(transactionManager = "testTransactionManager")
@Transactional
public class UserServiceTest {

    @Autowired
    private DefaultUserService userService;

    @Before
    public void setup() {
        userService.setTableName("mytesttable");
    }
    @Test
    public void test() {
        // test with userService;
        userService.listAll();
    }
}

请注意它使用了context-test.xml,该文件已经导入了原始的context.xml

<import resource="classpath:context.xml"/>

很不幸,在测试开始时,Spring 抛出了异常:

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'mypackage.UserServiceTest': 
Injection of autowired dependencies failed; 
nested exception is org.springframework.beans.factory.BeanCreationException: 
Could not autowire field: 
private mypackage.DefaultUserService mypackage.userService

nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: 
No qualifying bean of type [mypackage.DefaultUserService] 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)}

我不确定哪里出了问题,为什么Spring找不到我定义的DefaultUserService bean?


你的 <bean> 声明在 context-test.xml 文件中吗? - Sotirios Delimanolis
@Sotirios,请看我的更新的问题,我有那个声明。 - Freewind
@Dan,是的。Spring无法为我的测试注入“DefaultUserService”bean。 - Freewind
你的context.xml文件中有<context:annotation-config />吗?顺便问一下,在UserServiceTest中不应该有一个userService的setter方法吗? - Dan
显示剩余4条评论
3个回答

2
尝试将类DefaultUserService替换为接口UserService
public class UserServiceTest {

    @Autowired
    private UserService userService;
    ....

}

它可以工作,但是我无法调用“setTableName(...)”来设置我的测试表名称,因为UserService没有这样的方法声明。 - Freewind

2
由于@Transactional将bean置于jdk代理后,实现了UserService接口,因此该bean仅可用作UserService而非DefaultUserService。 请参见https://dev59.com/ZHbZa4cB1Zd3GeqPMPxp#18875681
您可以尝试使用属性占位符@Value("${someprop}")设置表名,并在测试上下文中定义该属性,或创建另一个接口来公开setTableName(),并将该辅助接口自动装配到测试用例中。
我不确定是否有任何简单的解决方案,我认为这个任务可以归入Spring测试上下文框架中的bean重新定义问题 Spring beans redefinition in unit test environment

1
你的 implementing class 没有定义 tableName 属性的 getter。Spring IOC 容器基于 POJO 模型操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接