一个简单的 Dao 集成测试不起作用

Posted

技术标签:

【中文标题】一个简单的 Dao 集成测试不起作用【英文标题】:A simple Dao integration test not working 【发布时间】:2012-01-17 10:15:07 【问题描述】:

这是一个非常简单的测试,关于在数据库中持久化一个临时的 Person 对象,然后验证该对象是否保存在 database 与瞬态 Person 对象相同。 测试开始了

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/daoIntegration-test.xml")
@Transactional
public class HibernatePersonDaoIntegrationTest 
    @Autowired
    private PersonDao PersonDao;
    @Autowired
    private SessionFactory sessionFactory;
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Test
    public void shouldSavePerson() 
        //Given
        Person person = new Person();

        //When
        PersonDao.savePerson(person);

        //Then ----THIS ASSERTION PASSES!!!
        assertThat(person.getId(), notNullValue());
        //And ----THIS ONE FAILS!!!
        Person persistedPerson = jdbcTemplate.queryForObject("select * from table_Person", Person.class);
        assertThat(persistedPerson, is(person));
    

我的 daoIntegration-test.xml

<jdbc:embedded-database id="dataSource" type="HSQL"/>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="packagesToScan" value="com.domain"/>
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.hbm2ddl.auto">create</prop>
        </props>
    </property>
</bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"/>
</bean> 
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

域类是:

@Entity
@Table(name="table_Person")
public class Person 

    @Id
    @TableGenerator(name = "seq_table", table = "GENERATOR_TABLE")
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "seq_table")
    public Long getId() 
        return id;
    

    public void setId(Long id) 
        this.id = id;
    

    private Long id;
    private String personFirstName;
...

第一个断言通过,但第二个失败,我在某个地方犯了一个愚蠢的错误,但不知道在哪里!!!

【问题讨论】:

person 和persistedPerson 是两个不同的实例,所以它们不相等。它们可能是等价的。例如 Person.ID = persistedPerson.ID 等。您可以覆盖 Person 类的 equals 运算符,但看到您还没有这样做可能会导致问题,因此最好检查一些 Person 属性。 我覆盖了equals和hashcode,问题是实体没有保存在数据库中,刷新它解决了@Tomasz建议的问题 【参考方案1】:

您正在执行SELECT * 查询,该查询仅在数据库中有一行时返回一个对象。

如果查询不只返回一行,或者不只返回一个对象,则抛出IncorrectResultSizeDataAccessException

你确定没有抛出异常吗?

您的 Person 类是否实现了 equals 和 hashCode correctly?如果 is() 方法依赖于这些,那么它不会比您的实现所允许的更好。

【讨论】:

【参考方案2】:

第一个可能的问题

第二个断言失败只是因为它返回了Person 对象的不同实例。由于您没有 (?) 定义 equals()/hashCode(),因此 is() 匹配器失败。

实现它们(这通常是 Hibernate 的一个好主意)。

第二个可能的问题

第一个断言通过是因为 Hibernate 从 seq_table 获取了 id,但还没有刷新实体本身。这意味着实体在一级缓存中,但尚未在数据库中。因此,当您直接使用 JDBC 查询数据库时:

jdbcTemplate.queryForObject("select * from table_Person", Person.class);

找不到记录。保存实体后调用flush() 或使用JPA 查询对象。 Hibernate 足够聪明,可以flush() 事先查询。

【讨论】:

以上是关于一个简单的 Dao 集成测试不起作用的主要内容,如果未能解决你的问题,请参考以下文章

@WithMockUser 在集成测试中不起作用 - Spring boot

Spring启动集成测试回滚不起作用

Spring/JTA/JPA DAO 集成测试不回滚?

使用 Spring Test 自动回滚 DAO 集成测试是一种好习惯吗?

不可能用 DAO mock 编写集成测试控制器?

使用 Redis 进行集成测试