Spring和JUnit注释测试:在单独的事务中创建fixture

时间:2010-05-26 16:08:44

标签: hibernate spring junit annotations

我正在用Spring和JUnit测试我的Hibernate DAO。

我希望每个测试方法都以预先填充的DB开始,即Java对象已经保存在数据库中,已经提交了一个Hibernate事务。我怎么能这样做?

使用@After和@Before,方法在与@Test和@Transactional装饰的方法相同的Hibernate事务中执行(在实际测试方法启动时,第一级缓存可能不会刷新)。 @BeforeTransaction和@AfterTransaction显然不能与Hibernate一起使用,因为除了@ Before / AfterTransaction之外,即使该方法使用@Transactional注释,它们也不会创建事务。

有什么建议吗?

2 个答案:

答案 0 :(得分:5)

一种方法是使用事务方法将您的初始化逻辑外部化到外部服务,这些方法是从测试类中的@BeforeTransaction和@AfterTransaction注释方法执行的。

这种方法的另一个好处是可以跨测试重用初始化代码。

例如,您可以使用像here这样的SpringJunit4ClassRunner:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"testContext.xml","services.xml"})
public class MyServiceTest {

    @Autowired    
    private TestDataService testDataService;

    @Before
    public void setUp(){
        testDataService.addTestData();
    }

    @Test
    public void testSomething() throws Exception {
         // ...
    }
}


public interface TestDataService {

    void addTestData();

}

public class TestDataServiceImpl implements TestDataService {

    @Transactional
    public void addTestData(){
        // TODO
    }

}

这是我们在基于Spring的项目中所做的事情。

确保transactional configuration正确无误。如果要避免类/接口分离,请在元素中将proxy-target-class设置为true。

答案 1 :(得分:2)

dbUnit是一个很好的工作框架。

简而言之,它应该从setUp()方法开始,它会从指定的表中删除所有内容,然后用XML文件中的内容填充它们。

否则,您可以尝试在新事务中执行setUp()方法,如下所示:

@Before
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void setUp() {
    // initial logic .. 
}