I'm trying to set up testing with an H2 in-memory database for my Spring MVC application.
Right now, all my configuration for Hibernate is in a Java file PersistenceConfig.java
and it holds the SessionFactory
with all the Hibernate configuration.
However, my testing context is in XML because it was easier that way - is there any way to make this work? Right now, when I run my tests, all I get is errors because it can't connect to MySQL, which it shouldn't even be trying to do.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
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-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
http://www.springframework.org/schema/jdbc
http://www.springframework.org/schema/jdbc/spring-jdbc-4.0.xsd">
<!-- annotation support -->
<context:annotation-config/>
<!-- support for transaction -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="com.package.configuration" />
<context:component-scan base-package="com.package.models" />
<!-- H2 datasource -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:test;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS">
<jdbc:script location="classpath:reset_database.sql"/>
<jdbc:script location="classpath:create_testdata.sql"/>
</jdbc:initialize-database>
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="persistenceConfig" class="com.package.configuration.PersistenceConfig"/>
<bean id="userDao" class="com.package.models.user.UserDao"/>
</beans>
My tester class looks like
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"/test-context.xml",
"classpath:/spring/spring-security.xml"})
@Transactional
public class UserTest {
private UserDao userDao = new UserDao();
private static User user;
@Autowired
@Qualifier("sessionFactory")
private static SessionFactory sessionFactory;
@BeforeClass
public static void initUser() {
user = new User(...);
}
@Test
public void testSave() throws Exception {
userDao.save(user);
User foundUser = userDao.findByUuid(user.getUuid());
assertEquals(foundUser.getUuid(), user.getUuid());
}
}
The sessionFactory
is not being Autowired and the userDao
never gets it.
My UserDao
calls PersistenceConfig.sessionFactory()
in its constructor, and PersistenceConfig
supplies it with a sessionFactory
that corresponds to MySQL. I need to somehow switch that out for a H2 sessionFactory
.
Am I going about this completely wrong?
It appears that when you are injecting you sessionFactory
it is loading PersistenceConfig.java
with it, generally when you inject one object others dependencies are injected too. If I were you, I would use hibertane.hbm.xml
to configure you test connection, it overrides all others configurations...
You are creating the UserDao
object yourself
private UserDao userDao = new UserDao();
Spring can only inject an object whose lifecycle it manages.
Get a UserDao
bean from your context ( @Autowired
it) if you have one (or add one if you don't).
For testing you can use your PersistenceConfig. Instead of setting up a complete new context I would split the distinct beans into @Profile configurations:
@Profile("test")
@Configuration
public class TestConfig {
@Bean public DataSource dataSource() {
// return Test bean
}
}
@Profile("production")
@Configuration
public class ProductionConfig {
@Bean public DataSource dataSource() {
// return productiv bean
}
}
@ActiveProfiles("test")
public class DatasourceTest {
@Test
public void test() {
// assertions
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.