@BeforeClass和Spring @TestExecutionListener beforeTestClass()之间有什么区别

时间:2012-09-13 10:53:56

标签: junit4 spring-test

使用JUnit @BeforeClass和Spring @TestExecutionListener beforeTestClass(TestContext testContext)“hook”之间有什么区别?如果有差异,在哪种情况下使用哪一个?

Maven依赖关系:
spring-core:3.0.6.RELEASE
spring-context:3.0.6.RELEASE
弹簧试验:3.0.6.RELEASE
spring-data-commons-core:1.2.0.M1
spring-data-mongodb:1.0.0.M4
mongo-java-driver:2.7.3
junit:4.9
cglib:2.2

使用JUnit @BeforeClass注释:

import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;

@ContextConfiguration(locations = { "classpath:test-config.xml" })
public class TestNothing extends AbstractJUnit4SpringContextTests {

    @Autowired
    PersonRepository repo;

    @BeforeClass
    public static void runBefore() {
        System.out.println("@BeforeClass: set up.");
    }

    @Test
    public void testInit() {
        Assert.assertTrue(repo.findAll().size() == 0 );
    }
}

=> @BeforeClass: set up.
=> Process finished with exit code 0

使用Spring钩子:

(1)覆盖beforeTestClass(TextContext testContext):

import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;

public class BeforeClassHook extends AbstractTestExecutionListener {

    public BeforeClassHook() { }

    @Override
    public void beforeTestClass(TestContext testContext) {
        System.out.println("BeforeClassHook.beforeTestClass(): set up.");
    }
}

(2)使用@TestExecutionListeners注释:

import org.springframework.test.context.TestExecutionListeners;  
// other imports are the same    

@ContextConfiguration(locations = { "classpath:test-config.xml" })
@TestExecutionListeners(BeforeClassHook.class)
public class TestNothing extends AbstractJUnit4SpringContextTests {

    @Autowired
    PersonRepository repo;

    @Test
    public void testInit() {
        Assert.assertTrue(repo.findAll().size() == 0 );
    }
}

=> BeforeClassHook.beforeTestClass(): set up.
=> Process finished with exit code 0

2 个答案:

答案 0 :(得分:19)

TestExecutionListeners是一种外部化工具测试的可重用代码的方法。

因此,如果您实现TestExecutionListener,则可以在测试类层次结构中以及可能跨项目重用它,具体取决于您的需求。

另一方面,@BeforeClass方法当然只能在单个测试类层次结构中使用。

但是,请注意,JUnit还支持Rules:如果您实现org.junit.rules.TestRule,您可以将其声明为@ClassRule以实现相同的目标......还有一个额外的好处: JUnit规则可以像Spring TestExecutionListener一样重用。

所以这真的取决于你的用例。如果您只需要在单个测试类或单个测试类层次结构中使用“课前”功能,那么最好只使用实现@BeforeClass方法的简单路径。但是,如果您预计在不同的测试类层次结构或项目中需要“课前”功能,则应考虑实现自定义TestExecutionListener或JUnit规则。

Spring TestExecutionListener优于JUnit规则的一个好处是TestExecutionListener可以访问TestContext,因此可以访问JUnit规则将导致的Spring ApplicationContext没有权限。此外,TestExecutionListener可以是automatically discoveredordered

相关资源

此致

Sam(Spring TestContext Framework的作者)

答案 1 :(得分:2)

@BeforeClass的第一个解决方案没有加载应用程序上下文。我做了扩展AbstractJUnit4SpringContextTests并定义了@ContextConfiguration。 我认为listner是在@beforeclass方法之前加载上下文的唯一方法。或者甚至更好地扩展SpringJUnit4ClassRunner类,如提到here