2011-03-14 195 views
0

我相信这样的问题被问了个遍again.but我觉得有东西在这里,我需要为所有人理解一次。如何集成测试正常使用Hibernate 3弹簧3.0.5进行与Spring事务管理(Maven项目)

我必须承认,我很差劲的undertanding春天TransactionManagement中是如何工作的,但我想我得到了一个集成测试意味着什么,直到现在在哪里我完全糊涂了。

这里是我写我的集成测试(我prefere集成测试单元测试时,我来测试应用程序的数据层,也许是个坏习惯)

我自动装配的对象,加上其在setup()性质,坚持他们有供后面实例的使用与像getUser()findUser/findAll()方法,然后删除所有的人都在拆卸。我认为这在我自己打开和关闭交易之前已经奏效。

我决定试用一下弹簧TransactionManagement中的事务性注释。

问题1
当我不添加模型用户上下文中的测试失败,因为我相信组件 - 扫描不工作: 这是错误

没有匹配发现依赖关系的类型为[com.myproject.perso.admintest.model.User]的bean:预计至少有1个bean符合此依赖关系的自动连线候选。依赖注解: {@ org.springframework.beans.factory.annotation.Autowired(所需=真)}

i,那么必须取消注释它,同为DAO

问题2

当仅存在单一的测试(testGetUser)和i具有仅在setupteardowncreateUser(user1)delete(user1)。测试是成功的。即使在setup和teardown中使用相同的配置,但是这次使用testFindUser,它仍然对数据库中的数据成功,然后使用拆卸删除。但一旦我取消在设置的createUser(用户2)和删除(用户2)在拆解除了USE1创建和删除然后抛出这个

无法插入:[com.myproject.perso.admintest.model。用户]; SQL [插入用户(电子邮件,密码,用户名)值(?,?,?)];约束[null];嵌套的例外是org.hibernate.exception.ConstraintViolationException:

我理解它有没有被刷新(尽管我没有得到它非常好)通过阅读其他人的帖子在会议上做的,但我的问题是什么时候春天转换进来?

问题
是有毛病我测试?
,如果我想通过在测试中创造POJO而不是使用DBUnit的例如用于我应该如何创建这个测试夹具,以保持我的做法。
什么是春季交易管理呢。感谢

这里是我的代码

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath:WEB-INF/testadmin-webapp-config.xml"}) 
public class UserDAOImplTest { 


private UserDAO userDao; 
@Autowired 
public void setDao(UserDAO userDao){ 
    this.userDao = userDao; 
} 

@Autowired 
User user1; 

@Autowired 
User user2; 

public UserDAOImplTest() { 
} 

@Before 
public void setUp() { 

    user1.setEmail("[email protected]"); 
    user1.setPassword("mypass"); 
    user1.setUsername("user1"); 

    user2.setEmail("[email protected]"); 
    user2.setPassword("password"); 
    user2.setUsername("user2"); 

    userDao.createUser(user1); 
    userDao.createUser(user2); 
} 

@After 
public void tearDown() { 
    userDao.delete(user1); 
    userDao.delete(user2); 
} 



/** 
* Test of getUser method, of class UserDAOImpl. 
*/ 
@Test 
public void testGetUser() { 
    System.out.println("getUser test"); 

    User expResult = user1; 
    User result = userDao.getUser(user1.getId()); 

    Assert.assertEquals(expResult.getId(), result.getId()); 
    Assert.assertEquals(expResult.getEmail(), result.getEmail()); 


    } 

    @Test 
    public void testFindUser() { 
    System.out.println("findUser"); 
    Assert.assertTrue(true); 

    } 
} 

我的DAO接口看起来那么

public interface UserDAO { 

User getUser(Long userId); 
User findUser(String name); 
List<User> getAllUsers(); 
void createUser(User user); 
void delete(User user); 
void updateUser(User user); 

} 

它的实现是像这样:

@Repository("UserDAO") 
@Transactional 
public class UserDAOImpl implements UserDAO { 

HibernateTemplate hibernateTemplate; 

@Autowired 
public void setSessionFactory(SessionFactory sessionFactory) { 
    this.hibernateTemplate = new HibernateTemplate(sessionFactory); 
} 

@Override 
public User getUser(Long userId) { 
    return hibernateTemplate.get(User.class, userId); 
} 

@Override 
public User findUser(String username) { 
    List found= hibernateTemplate.find("from User u where u.username= ?", username); 
    return (found.size() == 1) ? (User) found.get(0) : new User(); 
} 

//...... 

@Override 
@Transactional 
public void createUser(User user) { 
    hibernateTemplate.save(user); 
} 

@Override 
@Transactional(readOnly=false) 
public void delete(User user) { 
    hibernateTemplate.delete(user); 
} 

// .....

my User POJO is like so 

@Id @GeneratedValue(strategy=GenerationType.IDENTITY) 
private Long Id; 
@Column(name="username" ,unique=true) 
private String username; 
@Column(name="password") 
private String password; 
@Column(name="email", unique=true) 
private String email; 

这里是我的测试环境文件

<!-- for i left out some part in order to be concise --> 
<context:annotation-config /> 
<context:component-scan base-package="com.myproject.perso.abmintest" /> 
<bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="${jdbc.driverClassName}" /> 
    <property name="url" value="${jdbc.url}" /> 
    <property name="username" value="${jdbc.username}" /> 
    <property name="password" value="${jdbc.password}" /> 
</bean> 
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" > 
    <property name="dataSource" ref="datasource" /> 
    <property name="packagesToScan" value="com.myproject.perso.admintest.model" /> 
    <property name="hibernateProperties" > 
     <props> 
      <prop key="hibernate.dialect">${hibernate.dialect}</prop> 
      <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> 
      <prop key="hibernate.format_sql">${hibernate.format_sql}</prop> 
      <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl}</prop> 
     </props> 
    </property> 
</bean> 
<tx:annotation-driven /> 
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory" ref="sessionFactory" /> 
</bean> 

<!-- Model Section--> 
<!--<bean id="user" class="com.myproject.admintest.model.User" />--> 

<!-- Model Section End--> 
<!--DAO--> 
<!--<bean id="userDao" class="com.myproject.admintest.dao.UserDAOImpl" />--> 

<!--DAO end --> 

这里是我的POM:

org.springframework (most of spring stuff including spring-asm)3.0.5.RELEASE 
org.hibernate:hibernate-core 3.6.1.Final 
org.hibernate:hibernate-cglig-repack 2.1_3 
log4j:log4j1.2.14 
org.slf4j:slf4j-log4j12 1.5.2 
junit:junit 4.5 
commons-collections:commons-collections 3.2.1 
jboss:javassist 3.7.ga 
commons-logging:commons-logging 1.1.1 

完全POM可以发现here

回答

1

不要自动线的用户对象中,然后创建设置方法。

如果将@Transactional注释添加到测试类中,Spring将在运行测试之前启动事务(&设置方法) - 将测试作为事务的一部分运行,然后回滚事务。这样,您不必在tearDown方法中编写代码来明确删除对象(撤消设置中完成的操作)。

您必须在会话中调用flush/clear - 通过获取对注入到测试中的SessionFactory的引用,以强制从数据库中重新获取对象时触发查询&。

+0

对不起,延迟,我知道你想说什么,我必须承认它不够清楚。你说的“ ”。这样你就不必在tearDown方法中编写代码来显式删除对象(撤销在设置中完成的事情)。“那意味着为每个测试创建一个新的对象? – 2011-03-31 18:32:33

2

简简单单就哥们

@Autowired 
private UserDAO userDao; 

private User user1; 

private User user2; 

@Before 
public void setUp() { 
    user1 = new User(); 
    user1.setEmail("[email protected]"); 
    user1.setPassword("mypass"); 
    user1.setUsername("user1"); 

    user2 = new User(); 
    user2.setEmail("[email protected]"); 
    user2.setPassword("password"); 
    user2.setUsername("user2"); 
} 

如果把创建用户的测试方法

@Test 
public void testGetUser() { 
    userDao.create(user1); 

    User expResult = user1; 
    User result = userDao.getUser(user1.getId()); 

    Assert.assertEquals(expResult.getId(), result.getId()); 
    Assert.assertEquals(expResult.getEmail(), result.getEmail()); 


} 

您可以添加@TransactionConfiguration回滚你的事务,如创建,更新,删除操作会更好。

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration({"classpath:WEB-INF/testadmin-webapp-config.xml"}) 
@TransactionConfiguration(defaultRollback=true) 
+0

感谢您的示例adisembiring,真的很感激它。但是,我确实有一个问题,那么如何测试集合,比如'testGetAll()'如何在测试该数据库之前提供数据中的数据。实际上,这就是为什么我将一些测试对象保存在'setUp()'方法并在拆解中清除它们。再次感谢 – 2011-04-03 17:10:34

+0

把userDao.create(user1);在测试方法中,然后使用你的dao通过用户id找到用户。 您可以使用 @TransactionConfiguration(defaultRollback = true) 来回滚保存的用户,它会在您运行测试之前返回数据库的第一个状态。所以你不需要使用tearDown来删除用户 – 2011-04-04 01:33:35

相关问题