Spring + Testing tests TestNG, DAO input with annotations fails

At first I did not mention what was the key component of this problem: here I am using TestNG.

I have a persistence DAO layer. It works great as part of my small web application (I have a classic controller, service, DAO design). I can update this question along with my XML documents.

My service level

@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... } 

My DAO layer

 @Repository public class UserDaoImplHibernate implements UserDao { @Autowired private SessionFactory sessionFactory; // My methods using sessionFactory & "talking" to the Db via the sessionFactory } 

And here is my test class

 @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... } 

But for my test class, Autowiring userDao always returns Null , I'm just starting to do tests in Spring, and I'm a bit lost. Any pointers are welcome.


Last edited by Boris Treukhov

 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... } 

And this is my 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> 

I did not add repository-config.xml as this is enough to access userDao . I still get userDao equal to zero though.

Thank you in advance

+4
source share
1 answer

If you create unit tests, the Spring IoC function is not available (as provided by the developers of the framework), because you test your objects in isolation (i.e. you mock only the minimal set of interfaces that the test needs to complete). In this case, you must manually enter your mock repository, for example, in the @Before initialization method. The whole idea is that your classes depend only on interfaces, so basically the Spring container estimates which class should be used as an implementation of the interface, but when you create a unit test, you need to strictly control which interface methods have been called (and have minimal set of dependencies), so you do the injection manually.

If you are doing integration testing, you must have an instance of the Spring IoC container, and for this you should use the jUnit (assuming you're using jUnit) specific test runner, as described in the Spring testing documentation .

So, back to the question, you have what looks like a simple unit test on jUnit, and the Spring container is not used. So, if you are going to use the Spring TestContext structure, you should have something like

  @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"/path-to-app-config.xml", "/your-test-specific-config.xml"}) public class UserDaoImplHibernateTests 

instead of @Component .

update in case of TestNg, I think it should be (I used Spring Injection Dependency with TestNG as a reference)

  @ContextConfiguration(locations={"/path-to-app-config.xml", "/your-test-specific-config.xml"}) public class UserDaoImplHibernateTests extends AbstractTestNGSpringContextTests 

See also: What is the difference between integration and unit tests?

+11
source

Source: https://habr.com/ru/post/1442381/


All Articles