В чем разница между @BeforeClass и Spring @TestExecutionListener beforeTestClass ()

В чем разница между использованием JUnit @BeforeClass и Spring @TestExecutionListener beforeTestClass (TestContext testContext) "зацеп"? Если есть разница, какой из них использовать при каких обстоятельствах?

Зависимости Maven:
spring-core: 3.0.6.RELEASE
spring-context: 3.0.6.RELEASE
spring-test: 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

Использование пружинного крючка:

(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

person rallison    schedule 13.09.2012    source источник


Ответы (2)


TestExecutionListeners - это способ экстернализации повторно используемого кода, инструментария ваших тестов.

Таким образом, если вы реализуете TestExecutionListener, вы можете повторно использовать его в иерархиях тестовых классов и, возможно, в проектах, в зависимости от ваших потребностей.

С другой стороны, метод @BeforeClass, естественно, может использоваться только в пределах одной иерархии тестовых классов.

Однако обратите внимание, что JUnit также поддерживает правила: если вы реализуете org.junit.rules.TestRule, вы можете объявить это как @ClassRule для достижения того же самого ... с дополнительным преимуществом, заключающимся в том, что правило JUnit можно повторно использовать так же, как Spring TestExecutionListener.

Так что это действительно зависит от вашего варианта использования. Если вам нужно использовать только функцию «до класса» в одном тестовом классе или в одной иерархии тестовых классов, тогда вам лучше пойти простым путем, просто реализовав @BeforeClass метод. Однако, если вы предвидите, что вам потребуется функциональность «до класса» в разных иерархиях тестовых классов или между проектами, вам следует подумать о реализации пользовательского TestExecutionListener или правила JUnit.

Преимущество Spring TestExecutionListener перед правилом JUnit состоит в том, что TestExecutionListener имеет доступ к TestContext и, следовательно, доступ к Spring ApplicationContext, к которому правило JUnit не имеет доступа. Кроме того, TestExecutionListener может быть обнаруживается автоматически и заказал.

Связанные ресурсы:

С уважением,

Сэм (автор Spring TestContext Framework)

person Sam Brannen    schedule 04.10.2012
comment
Есть ли способ установить порядок слушателей? (Например, я хочу запустить код до того, как произойдет загрузка контекста Spring) - person Wim Deblauwe; 11.06.2014
comment
Да, вы можете контролировать порядок слушателей, когда объявляете @TestExecutionListeners в своем тестовом классе. См. Слайды 27-33 в моем Spring 3.1 и поддержке тестирования MVC и обратитесь к документации Javadoc для @ TestExecutionListeners. - person Sam Brannen; 11.06.2014
comment
Просто прочтите обе ссылки, но я не вижу ничего, связанного с порядком. Должны ли они запускаться в том порядке, в котором вы их объявляете в аннотации? - person Wim Deblauwe; 12.06.2014
comment
Да, TestContextManager поддерживает их как List<TestExecutionListener> testExecutionListeners, который представляет собой упорядоченный список, построенный на основе порядка, в котором слушатели объявлены через @TestExecutionListeners. - person Sam Brannen; 12.06.2014
comment
А если использовать наследование слушателей? - person Wim Deblauwe; 12.06.2014
comment
Пожалуйста, обратитесь к Javadoc для @ TestExecutionListeners # inheritListeners. - person Sam Brannen; 13.06.2014

Первое решение с @BeforeClass не имеет загруженного контекста приложения. Я расширил AbstractJUnit4SpringContextTests и определил @ContextConfiguration. Я думаю, что listner - это единственный способ загрузить контекст до метода @beforeclass. Или даже лучше расширить класс SpringJUnit4ClassRunner, как упоминалось здесь

person nir    schedule 16.09.2013