问题描述
我首先没有提到此问题的关键因素是什么:我在这里使用TestNG.
I first did not mention what was the key component of this issue: I am using TestNG here.
我有一个执行持久性的DAO层.作为我的小型Web应用程序的一部分,它可以正常工作(我有经典的Controller,Service,DAO层设计).如果需要,我可以使用XML更新此问题.
I have a DAO layer performing persistence. It works fine as part of my little web app (I have a classic Controller, Service, DAO layers design). I can update this question with my XMLs if required.
我的服务层
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public GoodVibeUserDetails getUser(String username) throws UsernameNotFoundException {
GoodVibeUserDetails user = userDao.getDetailsRolesAndImagesForUser(username);
return user;
}
// more methods...
}
我的DAO层
@Repository
public class UserDaoImplHibernate implements UserDao {
@Autowired
private SessionFactory sessionFactory;
// My methods using sessionFactory & "talking" to the Db via the sessionFactory
}
这是我的测试班
@Component
public class UserDaoImplHibernateTests{
@Autowired
private UserDao userDao;
private GoodVibeUserDetails user;
@BeforeMethod
public void beforeEachMethod() throws ParseException{
user = new GoodVibeUserDetails();
user.setUsername("adrien");
user.setActive(true);
// & so on...
}
/*
* When everything is fine - test cases
*/
@Test
public void shouldAcceptRegistrationAndReturnUserWithId() throws Exception{
assertNotNull(userDao) ;
user = userDao.registerUser(user);
assertNotNull(user.getId()) ;
}
// more test cases...
}
但是对于我的测试课程,自动装配userDao
总是返回 Null ,我只是在Spring才开始进行测试,所以我有点迷路了.欢迎任何指针.
But for my test class the Autowiring, userDao
always returns Null, I'm only starting to do tests in Spring and I'm a bit lost. Any pointers are welcome.
鲍里斯·特鲁霍夫(Boris Treukhov)回答后的最新修改
Latest edit after Boris Treukhov's answer
import ...
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;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.junit.Assert.assertNotNull;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/applicationContext.xml")
public class UserDaoImplHibernateTests{
@Autowired
@Qualifier("userDao")
private UserDao userDao;
private GoodVibeUserDetails user;
@BeforeMethod
public void beforeEachMethod() throws ParseException{
user = new GoodVibeUserDetails();
user.setUsername("adrien");
user.setActive(true);
// & so on...
}
/*
* When everything is fine - test cases
*/
@Test
public void shouldAcceptRegistrationAndReturnUserWithId() throws Exception{
assertNotNull(userDao) ;
user = userDao.registerUser(user);
assertNotNull(user.getId()) ;
}
// more test methods...
}
这是我的 applicationContext.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"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd" >
<!-- the application context definition scans within the base package of the application -->
<!-- for @Components, @Controller, @Service, @Configuration, etc. -->
<context:annotation-config />
<context:component-scan base-package="com.goodvibes" />
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" p:location="/WEB-INF/jdbc.properties" />
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
p:driverClassName="${jdbc.driverClassName}" p:url="${jdbc.databaseurl}"
p:username="${jdbc.username}" p:password="${jdbc.password}" />
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation">
<value>classpath:hibernate.cfg.xml</value>
</property>
<property name="configurationClass">
<value>org.hibernate.cfg.AnnotationConfiguration</value>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">${jdbc.dialect}</prop>
<prop key="hibernate.show_sql">${jdbc.show_sql}</prop>
<prop key="hibernate.connection.SetBigStringTryClob">true</prop>
<prop key="hibernate.jdbc.batch_size">0</prop>
</props>
</property>
</bean>
<tx:annotation-driven />
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
[...]
</beans>
我没有添加repository-config.xml,因为这足以访问userDao
.但是我仍然使userDao等于null.
I did not add a repository-config.xml as this should be enough to access userDao
. I still get userDao equal null though.
预先感谢
推荐答案
如果创建单元测试,则Spring IoC功能将不可用(这是框架设计者所期望的),因为您正在隔离地测试对象(即,仅嘲笑测试完成所需的最小接口集).在这种情况下,您应该手动注入模拟存储库,例如,在@Before测试初始化方法中.整个想法是,您的类仅依赖于接口,因此基本上,Spring容器会评估将哪个类用作接口实现,但是在创建单元测试时,您需要严格控制调用了哪些接口方法(并具有一个最小的依赖关系集),这就是为什么您手动执行注入.
If you create unit tests, Spring IoC functionality is unavailable(as it was intended by the framework designers), because you are testing your objects in isolation(i.e. you are mocking only minimal set of interfaces which are required for the test to complete). In this case you should inject your mock repository manually, for example in @Before test initialization method. The whole idea is that your classes only depend on interfaces, so basically Spring container evaluates which class to use as the interface implementation, but when you create a unit test you need to have a strict control of which interface methods were called(and have a minimal set of dependencies), that is why you perform the injection manually.
如果要进行集成测试,则应启动并运行一个Spring IoC容器实例,为此,您应使用特定于jUnit(假设您正在使用jUnit)的测试运行程序,如.
If you are doing integration testing, you should have a Spring IoC container instance up and running, for this to work you should use jUnit(assuming that you are using jUnit) specific test runner, as it described in the Spring documentation on testing.
因此,回到问题所在,您具有对jUnit的简单单元测试的外观,并且未使用Spring容器.因此,如果要使用Spring TestContext框架,则应该有类似
So, returning to the question, you have what looks like a simple unit test to jUnit, and the Spring container is not used. So, if you are going to use Spring TestContext framework, you should have something like
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/path-to-app-config.xml", "/your-test-specific-config.xml"})
public class UserDaoImplHibernateTests
而不是@Component
.
更新(我使用了以TestNG 为参考的Spring依赖注入
update in TestNg case I think it should be (I used Spring Dependency Injection with TestNG as the reference)
@ContextConfiguration(locations={"/path-to-app-config.xml", "/your-test-specific-config.xml"})
public class UserDaoImplHibernateTests extends AbstractTestNGSpringContextTests
另请参见:集成和单元之间有什么区别测试?
这篇关于Spring + TestNG集成测试,向DAO注入注解失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!