Бобовое переопределение Spring в среде модульного теста

Если вы используете Python 3:

for item in food:
    print('I like {}'.format(item))

Если вы используете 2, просто удалите скобки.

50
задан luboskrnac 3 October 2016 в 04:26
поделиться

9 ответов

я предложил бы пользовательский TestClass и некоторые легкие правила для местоположений пружинного bean.xml

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
    "classpath*:spring/*.xml",
    "classpath*:spring/persistence/*.xml",
    "classpath*:spring/mock/*.xml"})
@Transactional
@TestExecutionListeners({
    DependencyInjectionTestExecutionListener.class,
    TransactionalTestExecutionListener.class,
    DirtiesContextTestExecutionListener.class})
public abstract class AbstractHibernateTests implements ApplicationContextAware 
{

    /**
     * Logger for Subclasses.
     */
    protected final Logger LOG = LoggerFactory.getLogger(getClass());

    /**
     * The {@link ApplicationContext} that was injected into this test instance
     * via {@link #setApplicationContext(ApplicationContext)}.
     */
    protected ApplicationContext applicationContext;

    /**
     * Set the {@link ApplicationContext} to be used by this test instance,
     * provided via {@link ApplicationContextAware} semantics.
     */
    @Override
    public final void setApplicationContext(
            final ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
}

, если будет mock-bean.xml в указанном месте, то они переопределят весь "реальный" bean.xml в "нормальных" местоположениях - Ваши нормальные местоположения могли бы отличаться

, но... я никогда не буду смешивать ложные и неложные бобы, трудно проследить проблемы, когда приложение становится более старым.

18
ответ дан Vikdor 7 November 2019 в 11:06
поделиться

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

Поочередно мы использовали следующую установку с большим успехом, и я думаю, что это вполне близко к тому, что Вы хотите, я был бы сильно , рекомендуют это:

Для всех бобов, которым нужны различные реализации в различных контекстах, переключитесь на основанное на аннотации проводное соединение. Можно оставить другие как есть.

Реализация следующий набор аннотаций

 <context:component-scan base-package="com.foobar">
     <context:include-filter type="annotation" expression="com.foobar.annotations.StubRepository"/>
     <context:include-filter type="annotation" expression="com.foobar.annotations.TestScopedComponent"/>
     <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
 </context:component-scan>

Затем Вы аннотируете Ваш живой реализации с @Repository, Ваш тупик реализации с @StubRepository, любой код, который должен присутствовать в приспособлении модульного теста ТОЛЬКО с @TestScopedComponent. Можно столкнуться с необходимостью в паре большего количества аннотаций, но это большой запуск.

, Если у Вас есть много spring.xml, необходимо будет, вероятно, сделать несколько новых пружинных XML-файлов, которые в основном только содержат определения сканирования компонента. Вы обычно просто добавляли бы эти файлы к своему обычному списку @ContextConfiguration. Причина этого состоит в том, потому что Вы часто заканчиваете с различными конфигурациями сканирований контекста (доверяйте мне, Вы будете делать еще по крайней мере 1 аннотацию при выполнении веб-тестов который делает для 4 соответствующих комбинаций)

Затем, Вы в основном используете

@ContextConfiguration(locations = { "classpath:/path/to/root-config.xml" })
@RunWith(SpringJUnit4ClassRunner.class)

Примечание, которое эта установка делает не , позволяют Вам иметь переменные комбинации тупиковых/живых данных. Мы попробовали это, и я думаю, что привел к путанице, которую я не рекомендую никому ;) Мы или соединяем гостиницу проводом полный набор тупиков или полный набор живых сервисов.

Мы главным образом используем автосоединенные проводом тупиковые зависимости при тестировании gui около материала, где зависимости являются обычно довольно существенными. В более чистых областях кода мы используем более регулярное поблочное тестирование.

В нашей системе у нас есть следующие XML-файлы для сканирования компонента:

  • для регулярного веб-производства
  • для стартовой сети с тупиками только [1 111]
  • для интеграционных тестов (в junit)
  • для модульных тестов (в junit)
  • для веб-тестов селена (в junit)

, который Это означает, у нас полностью есть 5 различных конфигураций в масштабе всей системы, с которыми мы можем запустить приложение. Так как мы только используем аннотации, пружина достаточно быстра для автосоединения проводом даже тех модульных тестов, которые мы хотим соединенный проводом. Я знаю, что это нетрадиционно, но это является действительно большим.

интеграционные тесты, выполненные с полной живой установкой, и несколько раз, я решил стать действительно прагматически настроенным и хотеть иметь 5 живые проводки и единственная насмешка:

public class HybridTest {
   @Autowired
   MyTestSubject myTestSubject;


   @Test
   public void testWith5LiveServicesAndOneMock(){
     MyServiceLive service = myTestSubject.getMyService();
     try {
          MyService mock = EasyMock.create(...)
          myTestSubject.setMyService( mock);

           .. do funky test  with lots of live but one mock object

     } finally {
          myTestSubject.setMyService( service);
     }


   }
}

я знаю, что тестовые пуристы собираются быть на всем протяжении меня для этого. Но иногда это - просто очень прагматическое решение, которое оказывается очень изящным, когда альтернатива была бы действительно действительно ужасна. Снова это обычно находится в тех gui-близких областях.

16
ответ дан krosenvold 7 November 2019 в 11:06
поделиться

Можно также записать модульные тесты для не требования любых поисков вообще:

@ContextConfiguration(locations = { "classpath:/path/to/test-config.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
public class MyBeanTest {

    @Autowired
    private MyBean myBean; // the component under test

    @Test
    public void testMyBean() {
        ...
    }
}

Это дает простой способ к смешиванию и подгонке реальные файлы конфигурации с тестовыми файлами конфигурации.

, Например, при использовании в спящем режиме, я мог бы иметь свой sessionFactory боб в одном файле конфигурации (чтобы использоваться и в тестах и в главном приложении), и иметь бобом источника данных в другом файле конфигурации (можно было бы использовать DriverManagerDataSource для дб в оперативной памяти, другой мог бы использовать JNDI-поиск).

, Но, определенно примите во внимание @cletus предупреждение ;-)

4
ответ дан Community 7 November 2019 в 11:06
поделиться

Легкий. Вы используете контекст пользовательского приложения для своих модульных тестов. Или Вы не используете один вообще, и Вы вручную создаете и вводите свои бобы.

Это звучит мне как Ваше тестирование, могло бы быть немного слишком широким. Поблочное тестирование о тестировании, ну, в общем, единиц. Боб Spring является довольно хорошим примером единицы. Вам не должен быть нужен контекст целого приложения для этого. Я нахожу, что, если Ваше поблочное тестирование так высокого уровня, что Вам нужны сотни бобов, соединений с базой данных, и т.д. затем, у Вас есть действительно хрупкий модульный тест, который собирается повредиться на очень следующем изменении, будет тверд поддержать и действительно не добавляет много значения.

3
ответ дан cletus 7 November 2019 в 11:06
поделиться

Можно использовать импорт функция в контексте тестового приложения для загрузки в бобах напоминания, и переопределять тех Вы хотите. Например, мой источник данных напоминания обычно получается через поиск JNDI, но когда я тестирую, я использую источник данных DriverManager, таким образом, я не должен запускать сервер приложений для тестирования.

2
ответ дан duffymo 7 November 2019 в 11:06
поделиться

Возможно, Вы могли использовать спецификаторы для своих бобов? Вы переопределили бы бобы, которые Вы хотите копировать в контексте отдельного приложения и маркировать их спецификатором "тестом". В Ваших модульных тестах, при проводном соединении бобов всегда указывают спецификатор "тест" для использования ложных взлетов.

0
ответ дан Il-Bhima 7 November 2019 в 11:06
поделиться

Я хочу сделать то же самое, и мы считаем это необходимым.

Текущий механизм, который мы используем, довольно ручной, но он работает.

Скажем, вы хотите чтобы имитировать bean-компонент типа Y. Мы делаем каждый bean-компонент, имеющий эту зависимость, реализуя интерфейс - «IHasY». Это интерфейс

interface IHasY {
   public void setY(Y y);
}

Затем в нашем тесте мы вызываем метод util ...

 public static void insertMock(Y y) {
        Map invokers = BeanFactory.getInstance().getFactory("core").getBeansOfType(IHasY.class);
        for (Iterator iterator = invokers.values().iterator(); iterator.hasNext();) {
            IHasY invoker = (IHasY) iterator.next();
            invoker.setY(y);
        }
    }

Я не хочу создавать весь XML-файл только для того, чтобы внедрить эту новую зависимость, и поэтому мне это нравится.

Если вы Если вы хотите создать файл конфигурации xml, то можно было бы создать новую фабрику с фиктивными bean-компонентами и сделать фабрику по умолчанию родительской для этой фабрики. Убедитесь, что вы загружаете все свои бины из новой дочерней фабрики. При этом подфабрика переопределит bean-компоненты в родительской фабрике, когда идентификатор bean-компонента ' s одинаковы.

Если бы в моем тесте я мог программно создать фабрику, это было бы здорово. Использование xml слишком обременительно. Я хочу создать эту дочернюю фабрику с кодом. Затем каждый тест может настроить свою фабрику так, как он хочет. Нет никаких причин, по которым такая фабрика не будет работать.

0
ответ дан 7 November 2019 в 11:06
поделиться

Здесь перечислены некоторые очень сложные и мощные решения.

Но есть FAR, FAR более простой способ выполнить то, что просил Стас, который не включают изменение чего-либо, кроме одной строки кода в методе тестирования. Он работает как для модульных тестов, так и для интеграционных тестов Spring, для автоматических зависимостей, частных и защищенных полей.

Вот он:

junitx.util.PrivateAccessor.setField(testSubject, "fieldName", mockObject);
6
ответ дан 7 November 2019 в 11:06
поделиться

У меня нет очков репутации, чтобы накапливать ответ Даффимо, но я просто хотел вмешаться и сказать, что его ответ был «правильным» для меня.

Создайте экземпляр FileSystemXmlApplicationContext в настройка вашего модульного теста с помощью настраиваемого applicationContext.xml. В этом пользовательском xml вверху сделайте так, как указывает duffymo. Затем объявите ваши фиктивные бины, источники данных, не относящиеся к JNDI и т. Д., Которые переопределят идентификатор, объявленный при импорте.

Работал как мечта для меня.

1
ответ дан 7 November 2019 в 11:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: