SpringJUnit4ClassRunner инициализирует bean-компоненты для каждого теста?

Следующий тест показывает, что этот тестовый компонент дважды инициализируется Spring. Я надеюсь, что кто-нибудь может сказать мне, почему это так, поскольку это должно быть только один раз. Вот тест:

import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {} )
public class TestAfterPropsSet implements InitializingBean {

private static final Logger logger = Logger.getLogger(TestAfterPropsSet.class);

@Test
public void test1() {
    logger.debug("Test1");
}

@Test
public void test2() {
    logger.debug("Test2");      
}

public void afterPropertiesSet() throws Exception {
    logger.debug("Bean Initialized");       
}
} // end class

Вот файл бина:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

и вот результат:

2009-10-13 21:20:04,393 [TestAfterPropsSet.java 26] DEBUG - Bean Initialized
2009-10-13 21:20:04,393 [TestAfterPropsSet.java 17] DEBUG - Test1
2009-10-13 21:20:04,393 [TestAfterPropsSet.java 26] DEBUG - Bean Initialized
2009-10-13 21:20:04,393 [TestAfterPropsSet.java 22] DEBUG - Test2

person harschware    schedule 14.10.2009    source источник


Ответы (1)


Это не весенняя конвенция. Вы должны следовать соглашениям JUnit, т. е. инициализация или деконструкция всего пакета должны выполняться в @BeforeClass и @AfterClass соответственно, или вы можете использовать @Autowire и позволить Spring обрабатывать область объекта.

Для каждого теста будет создан новый набор. Это более очевидно в JUnit3, где вам нужно было создать новый набор, используя указанное имя теста.

Взгляните на JavaDoc:

Аннотация Test сообщает JUnit, что открытый метод void, к которому он прикреплен, может быть запущен как тестовый пример. Чтобы запустить метод, JUnit сначала создает новый экземпляр класса, а затем вызывает аннотированный метод. Любые исключения, выдаваемые тестом, будут сообщены JUnit как сбой. Если исключений не выдается, считается, что тест прошел успешно.

Ваш вариант использования немного озадачивает, поскольку ваш тест на самом деле ничего не делает, и нет bean-компонента, на который вы ссылаетесь. По умолчанию bean-компоненты Spring объявляются с атрибутом по умолчанию scope="singleton", поэтому, если бы вы действительно объявили bean-компонент, это был бы кешированный синглтон. Однако это не имеет ничего общего с выполнением метода.

person Droo    schedule 14.10.2009
comment
уведомление: реализует InitializingBean, превращая его в bean-компонент. Или, по крайней мере, я предполагаю по имени. И тот факт, что я могу @Autowire поля и тому подобное в него. Проблема с @BeforeClass заключается в том, что он выполняется до того, как Spring сделает инъекцию в тестовый класс. Поскольку мне нравится вводить тестовые ресурсы, это часто является проблемой. @Before и тому подобное также выполняются перед инъекцией, но выполняются для каждого теста. Лучшее, что я нашел, - это использовать afterPropertiesSet() из интерфейса InitiliazingBean и выполнить любую настройку, необходимую для ввода ресурсов. Проблема, которую я обнаружил, заключается в том, что afterPropertiesSet запускается перед каждым тестом. - person harschware; 15.10.2009
comment
Это имеет немного больше смысла. Я не уловил остальную часть вашего кода до того, как он был отредактирован, чтобы включить форматирование. Я почти уверен, что вы можете использовать lazy-init=true, чтобы Spring создавал экземпляры по запросу в @BeforeClass или @Before с использованием BeanFactory, но это не решает повторную инициализацию. Возможно, это только мое мнение, но я не думаю, что есть проблема с повторной инициализацией, если нет ограничения кода. - person Droo; 15.10.2009
comment
Исправление к моему комментарию: @Before и тому подобное также выполнить перед инъекцией не соответствует действительности. Я не думаю, что это сильно меняет этот вопрос. - person harschware; 16.10.2009