dirtiescontext spring что это

Краткое руководство по @DirtiesContext

Узнайте, как использовать аннотацию «@DirtiesContext весны» для тестирования

1. Обзор

В этом быстром учебнике мы узнаем о @DirtiesContext аннотация. Мы также покажем стандартный способ использования аннотации для тестирования.

2. @DirtiesContext

Если мы разохим @DirtiesContext на классе аннотация применяется к каждому методу в классе с данной КлассМод.

3. Тестирование без очистки весеннего контекста

Допустим, у нас есть Пользователь :

У нас также есть очень простой ПользовательКаш:

Мы создаем интеграционный тест для загрузки и тестирования полного приложения:

После добавления пользователя в кэш он печатает содержимое кэша:

Далее, РаспечататьКаш снова печатает кэш пользователя:

Он содержит имя, добавленное в предыдущем тесте:

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

4. Использование @DirtiesContext

addJohnDoeAndPrintCache метод тестирования добавляет пользователя в кэш. Мы также добавили @DirtiesContext аннотация, в которой говорится, что контекст должен закрыться в конце тестового метода:

Наконец, РаспечататьКачеАгайн снова печатает кэш:

5. Другие поддерживаемые этапы испытаний

В приведеном выше примере показана после текущего метода тестирования фаза. Давайте сделаем краткое резюме этапов:

5.1. Уровень класса

КлассМод параметры тестового класса определяют, когда контекст сбрасывается :

5.2. Методный уровень

МетодМод параметры для отдельного метода определяют, когда контекст сбрасывается :

6. Заключение

В этой статье мы представили @DirtiesContext тестирование аннотации.

Источник

Spring @DirtiesContext Annotation Example

In this article”Spring @DirtiesContext Annotation Example”, we will see an example of spring @DirtiesContext annotation. @DirtiesContext is a spring test annotation which is used to indicate that the application context cached should be removed and reloaded after each test run. The application context removed will also be closed.
@DirtiesContext can be declared at method level as well as class level. dirtiescontext

@DirtiesContext Flow “dirtiescontext”

If @DirtiesContext is declared at class level with classMode set to ClassMode.AFTER_CLASS then the application context will be closed after all the tests of the test class are run.

Example without @DirtiesContext

In our example will use an employee bean which will auto-wire then use the auto-wired bean in each test case. If we have not used @DirtiesContext annotation then we will have have one employee bean which will be shared by all test cases.

All the tests use the same employee instance as you can see employee name set in emp3Test() and the one fetched in the before method for the next test run are the same.

@DirtiesContext at Test Level

If we annotate a test method with @DirtiesContext then the context will be closed and removed from the cache after the test’s run. The context will be reloaded before the start of the next test.

@DirtiesContext at Class Level

Download the source code

This was an example about spring @DirtiesContext Annotation.

Источник

Spring Data JPA. JUnit тесты для Services. Часть 3

В этом уроке мы напишем интеграционные тесты для проверки наших сервисов с помощью JUnit. Довольно часто это требуется чтобы протестировать Service слой, именно это мы и будем делать.

О том что такое JUnit и для чего он можно почитать тут.

Тестировать мы будем только сервис BankService так как остальные тестируется сервисы тестируются аналогичным способом.

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

Шаг 0. Зависимости

Обратите внимание, что в первой части этой серии мы подключали две зависимости:

Первая зависимость это JUnit Framework для тестирования, вторая это поддержка Spring для тестирования.

Шаг 1. Конфигурирование Spring

Теперь нам нужно сконфигурировать Spring для тестов это можно сделать используя туже конфигурацию что и в первом уроке.

Разница между ними будет только в том что DataSource будет сконфигурирован под тестовую БД – testdb.

Не будем углубляться в подробности, так как все это было рассмотрено в первой части, мы то же самое модифицировали под нашу тестовую БД. Данная конфигурация будет отвечать за наш контекст и все beans которые мы в нем сконфигурировали, будут созданы после того как контекст запустится.

Шаг 2. Создание тестового класса

Давайте создадим тестовый класс со всеми аннотациями и ниже их рассмотрим:

Аннотации:

@DirtiesContext – говорит что ApplicationContext Spring будет связан с тестовым классом;

@RunWith(SpringJUnit4ClassRunner.class) – говорит JUnit-у что для запуска тестов нужно использовать спринговый ранер ;

@ContextConfiguration(classes = TestDataBaseConfig.class) – с помощью этой аннотации мы указываем какую конфигурацию контекста использовать, можно указывать несколько. Обратите внимание что мы указали конфигурацию, которую создали в первом шаге.

@WebAppConfiguration – используется для тестирования контроллеров например, чтобы иметь доступ к веб-ресурсам.

Для удобства и не обязательно:

Ну и на завершение был создан утильный класс, который бы создавал нужные нам экземпляры объектов:

Источник

Интеграция DBUnit и Spring TestContext Framework

С появлением в Spring 2.5 фреймворка TestContext интеграционное тестирование кода, работающего с базой данных, существенно упростилось. Появились аннотации для декларативного указания контекста, в котором должен выполняться тест, аннотации для управления транзакциями в рамках теста, а также базовые классы тестов для JUnit и TestNG. В этой статье я опишу вариант интеграции фреймворка TestContext с DBUnit, позволяющим инициализировать базу данных и сверить её состояние с ожидаемым по окончании выполнения теста.

Рассмотрим простой пример: нам нужно протестировать корректное сохранение доменного объекта в базу.

DAO, отвечающий за сохранение объекта:

Стоит отметить, что интеграционное тестирование DAO подразумевает комплексное тестирование DAO, маппинга доменного объекта и перзистенс-провайдера. В нашем случае в качестве последнего используем Hibernate. Для тестирования создадим Spring-контекст testContext.xml следующего содержания:

Теперь создадим тестовый класс, расширив стандартный класс Spring TestContext Framework для транзакционных тестов на базе JUnit. Аннотация @ContextConfiguration указывает на контекст (располагающийся, в нашем случае, в classpath), в котором необходимо выполнять данный тест. Это позволяет нам инъектировать тестируемый DAO с помощью аннотации @Autowired.

Базовый класс AbstractTransactionalJUnit4SpringContextTests сконфигурирован таким образом, что каждый тестовый метод выполняется в транзакции, которая по окончании метода откатывается.

Далее необходимо проверить, что данные действительно сохранились в базу. Можно инъектировать в тестовый класс EntityManager и прямо после вставки данных использовать его для проверки соответствующих ассертов. В большинстве случаев при написании DAO этого будет вполне достаточно для контроля корректности маппингов и логики DAO. Транзакция по завершении теста откатится, и условие отсутствия побочных эффектов теста будет соблюдено.

Однако возникают ситуации, когда нам необходимо всё-таки подтвердить транзакцию по окончании теста, убедиться в её корректном завершении и проверить, что именно сохранилось в базу — вплоть до полей конкретных таблиц. Отмечу, что такие проверки, скорее всего, жёстко привяжут тест к физике базы данных и существенно повысят его чувствительность. Кроме того, он может не выполниться в связке с другим перзистенс-провайдером ввиду отличий в структуре или именовании таблиц.

Базовые классы тестов, предоставляемые Spring, предлагают лишь возможность выполнить некоторые SQL-скрипты над тестовой базой. Рассмотрим, как нам может помочь DBUnit, и как интегрировать его с Spring TestContext Framework.

DBUnit позволяет описывать состояние базы данных без привязки к физическим типам данных — в виде набора данных XML. Вот исходный набор данных для нашего теста: он пуст, в нём объявлена единственная таблица persons, соответствующая нашему доменному классу.

А вот ожидаемый набор данных: таблица persons здесь содержит три записи.

Следует сказать, что в DBUnit существует и сокращённый вариант записи, в котором имя таблицы описывается тегом, а значения полей — атрибутами. Но полноразмерный формат в некоторых случаях бывает функциональнее.

Создадим аннотацию для тестового метода, указывающую, какой набор данных необходимо загрузить перед началом метода (атрибут before), и с каким набором данных сверить базу после его завершения (атрибут after):

Для обработки этой аннотации расширим стандартный тестовый класс AbstractTransactionalJUnit4SpringContextTests.

Статический вложенный класс DbunitTestExecutionListener расширяет слушатель AbstractExecutionListener — часть фреймворка TestContext. Он включается в жизненный цикл теста с помощью аннотации @TestExecutionListeners на тестовом класе.

Тестовый класс подключается к жизненному циклу теста в двух точках. Первая — это метод DbunitTestExecutionListener#beforeTestMethod, выполняющийся перед каждым тестовым методом. В нём слушатель проверяет наличие на текущем тестовом методе нашей аннотации @DbunitDataSets. При наличии аннотации он производит инициализацию тестировщика базы данных из фреймворка DBUnit. Имя файла с набором данных, подлежащим загрузке в базу перед началом теста, получается из поля before аннотации @DbunitDataSets. Значение поля after аннотации и экземпляр тестировщика сохраняются в поля тестового класса.

Вторая точка входа — это метод assertAfterTransaction(), отмеченный аннотацией @AfterTransaction, также являющейся частью фреймворка TestContext. Эта аннотация обеспечивает выполнение метода по завершении транзакции каждого тестового метода, отмеченного аннотацией @Transactional. В этом методе мы используем ранее сохранённые databaseTester и afterDatasetFileName, а также стандартный функционал DBUnit, чтобы сравнить состояние базы данных с ожидаемым.

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

Аннотация Rollback(false) обеспечивает подтверждение транзакции по окончании теста. Аннотация @DirtiesContext указывает на необходимость пересоздания контекста Spring перед следующим тестом в классе. В нашей аннотации @DbunitDataSets мы указали имена файлов, содержащих начальный и ожидаемый наборы данных DBUnit.

Ограничением приведённого варианта тестирования является необходимость пересоздавать Spring-контекст перед каждым тестовым методом. По завершении теста в базе остаются не только рабочие данные (которые легко может удалить как DBUnit, так и метод AbstractTransactionalJUnit4SpringContextTests#deleteFromTables), но и вспомогательные таблицы и последовательности перзистенс-провайдера. Таким образом, каждый тестовый метод должен быть помечен аннотацией @DirtiesContext. В таком случае перед каждым тестовым методом будет заново создан контекст Spring и экспортирована схема базы данных.

Можно, чтобы не тратить время на поднятие контекста, попробовать сделать в Before повторный экспорт схемы Hibernate, тогда получится обойтись без аннотаций @DirtiesContext. Но я не стал делать этого в базовом тестовом классе, прежде всего, чтобы не привязывать его к Hibernate. И потом, даже такая жёсткая очистка базы не дала бы уверенности в избавлении от всех возможных побочных эффектов, вроде кэширования.

В заключение хочу отметить, что абстрактный тест на базе TestNG пишется аналогично и ничем не отличается от теста на базе JUnit, кроме расширяемого базового класса — в данном случае это будет AbstractTransactionalTestNGSpringContextTests. Для своих целей я вынес слушатель DbunitTestExecutionListener в отдельный класс и реализовал два базовых класса для этих двух тестовых фреймворков.

Источник

Dirtiescontext spring что это

It is important to be able to perform some integration testing without requiring deployment to your application server or connecting to other enterprise infrastructure. This will enable you to test things such as:

The Spring Framework provides first-class support for integration testing in the spring-test module. The name of the actual JAR file might include the release version and might also be in the long org.springframework.test form, depending on where you get it from (see the section on Dependency Management for an explanation). This library includes the org.springframework.test package, which contains valuable classes for integration testing with a Spring container. This testing does not rely on an application server or other deployment environment. Such tests are slower to run than unit tests but much faster than the equivalent Selenium tests or remote tests that rely on deployment to an application server.

In Spring 2.5 and later, unit and integration testing support is provided in the form of the annotation-driven Spring TestContext Framework. The TestContext framework is agnostic of the actual testing framework in use, thus allowing instrumentation of tests in various environments including JUnit, TestNG, and so on.

15.2 Goals of Integration Testing

Spring’s integration testing support has the following primary goals:

The next few sections describe each goal and provide links to implementation and configuration details.

15.2.1 Context management and caching

The Spring TestContext Framework provides consistent loading of Spring ApplicationContext s and WebApplicationContext s as well as caching of those contexts. Support for the caching of loaded contexts is important, because startup time can become an issue — not because of the overhead of Spring itself, but because the objects instantiated by the Spring container take time to instantiate. For example, a project with 50 to 100 Hibernate mapping files might take 10 to 20 seconds to load the mapping files, and incurring that cost before running every test in every test fixture leads to slower overall test runs that reduce developer productivity.

Читайте также:  при судорогах в ногах какие препараты принимать таблетки мази витамины

Test classes typically declare either an array of resource locations for XML or Groovy configuration metadata — often in the classpath — or an array of annotated classes that is used to configure the application. These locations or classes are the same as or similar to those specified in web.xml or other configuration files for production deployments.

By default, once loaded, the configured ApplicationContext is reused for each test. Thus the setup cost is incurred only once per test suite, and subsequent test execution is much faster. In this context, the term test suite means all tests run in the same JVM — for example, all tests run from an Ant, Maven, or Gradle build for a given project or module. In the unlikely case that a test corrupts the application context and requires reloading — for example, by modifying a bean definition or the state of an application object — the TestContext framework can be configured to reload the configuration and rebuild the application context before executing the next test.

15.2.2 Dependency Injection of test fixtures

When the TestContext framework loads your application context, it can optionally configure instances of your test classes via Dependency Injection. This provides a convenient mechanism for setting up test fixtures using preconfigured beans from your application context. A strong benefit here is that you can reuse application contexts across various testing scenarios (e.g., for configuring Spring-managed object graphs, transactional proxies, DataSource s, etc.), thus avoiding the need to duplicate complex test fixture setup for individual test cases.

See dependency injection of test fixtures with the TestContext framework.

15.2.3 Transaction management

One common issue in tests that access a real database is their effect on the state of the persistence store. Even when you’re using a development database, changes to the state may affect future tests. Also, many operations — such as inserting or modifying persistent data — cannot be performed (or verified) outside a transaction.

The TestContext framework addresses this issue. By default, the framework will create and roll back a transaction for each test. You simply write code that can assume the existence of a transaction. If you call transactionally proxied objects in your tests, they will behave correctly, according to their configured transactional semantics. In addition, if a test method deletes the contents of selected tables while running within the transaction managed for the test, the transaction will roll back by default, and the database will return to its state prior to execution of the test. Transactional support is provided to a test via a PlatformTransactionManager bean defined in the test’s application context.

If you want a transaction to commit — unusual, but occasionally useful when you want a particular test to populate or modify the database — the TestContext framework can be instructed to cause the transaction to commit instead of roll back via the @Commit annotation.

See transaction management with the TestContext framework.

15.2.4 Support classes for integration testing

The Spring TestContext Framework provides several abstract support classes that simplify the writing of integration tests. These base test classes provide well-defined hooks into the testing framework as well as convenient instance variables and methods, which enable you to access:

In addition, you may want to create your own custom, application-wide superclass with instance variables and methods specific to your project.

See support classes for the TestContext framework.

15.3 JDBC Testing Support

The spring-jdbc module provides support for configuring and launching an embedded database which can be used in integration tests that interact with a database. For details, see Section 19.8, “Embedded database support” and Section 19.8.5, “Testing data access logic with an embedded database”.

15.4 Annotations

15.4.1 Spring Testing Annotations

The Spring Framework provides the following set of Spring-specific annotations that you can use in your unit and integration tests in conjunction with the TestContext framework. Refer to the corresponding javadocs for further information, including default attribute values, attribute aliases, and so on.

@BootstrapWith

@ContextConfiguration

@ContextConfiguration defines class-level metadata that is used to determine how to load and configure an ApplicationContext for integration tests. Specifically, @ContextConfiguration declares the application context resource locations or the annotated classes that will be used to load the context.

Resource locations are typically XML configuration files or Groovy scripts located in the classpath; whereas, annotated classes are typically @Configuration classes. However, resource locations can also refer to files and scripts in the file system, and annotated classes can be component classes, etc.

As an alternative or in addition to declaring resource locations or annotated classes, @ContextConfiguration may be used to declare ApplicationContextInitializer classes.

@ContextConfiguration provides support for inheriting resource locations or configuration classes as well as context initializers declared by superclasses by default.

See Section 15.5.4, “Context management” and the @ContextConfiguration javadocs for further details.

@WebAppConfiguration

To override the default, specify a different base resource path via the implicit value attribute. Both classpath: and file: resource prefixes are supported. If no resource prefix is supplied the path is assumed to be a file system resource.

@ContextHierarchy

@ContextHierarchy is a class-level annotation that is used to define a hierarchy of ApplicationContext s for integration tests. @ContextHierarchy should be declared with a list of one or more @ContextConfiguration instances, each of which defines a level in the context hierarchy. The following examples demonstrate the use of @ContextHierarchy within a single test class; however, @ContextHierarchy can also be used within a test class hierarchy.

If you need to merge or override the configuration for a given level of the context hierarchy within a test class hierarchy, you must explicitly name that level by supplying the same value to the name attribute in @ContextConfiguration at each corresponding level in the class hierarchy. See the section called “Context hierarchies” and the @ContextHierarchy javadocs for further examples.

@ActiveProfiles

@ActiveProfiles is a class-level annotation that is used to declare which bean definition profiles should be active when loading an ApplicationContext for an integration test.

See the section called “Context configuration with environment profiles” and the @ActiveProfiles javadocs for examples and further details.

@TestPropertySource

@TestPropertySource is a class-level annotation that is used to configure the locations of properties files and inlined properties to be added to the set of PropertySources in the Environment for an ApplicationContext loaded for an integration test.

Test property sources have higher precedence than those loaded from the operating system’s environment or Java system properties as well as property sources added by the application declaratively via @PropertySource or programmatically. Thus, test property sources can be used to selectively override properties defined in system and application property sources. Furthermore, inlined properties have higher precedence than properties loaded from resource locations.

The following example demonstrates how to declare a properties file from the classpath.

The following example demonstrates how to declare inlined properties.

@DirtiesContext

The following examples explain when the context would be dirtied for various configuration scenarios:

After the current test class, when declared on a class with class mode set to AFTER_CLASS (i.e., the default class mode).

Before each test method in the current test class, when declared on a class with class mode set to BEFORE_EACH_TEST_METHOD.

After each test method in the current test class, when declared on a class with class mode set to AFTER_EACH_TEST_METHOD.

After the current test, when declared on a method with the method mode set to AFTER_METHOD (i.e., the default method mode).

For further details regarding the EXHAUSTIVE and CURRENT_LEVEL algorithms see the DirtiesContext.HierarchyMode javadocs.

@TestExecutionListeners

@TestExecutionListeners supports inherited listeners by default. See the javadocs for an example and further details.

@Commit

@Rollback

When declared as a class-level annotation, @Rollback defines the default rollback semantics for all test methods within the test class hierarchy. When declared as a method-level annotation, @Rollback defines rollback semantics for the specific test method, potentially overriding class-level @Rollback or @Commit semantics.

@BeforeTransaction

@BeforeTransaction indicates that the annotated void method should be executed before a transaction is started for test methods configured to run within a transaction via Spring’s @Transactional annotation. As of Spring Framework 4.3, @BeforeTransaction methods are not required to be public and may be declared on Java 8 based interface default methods.

@AfterTransaction

@AfterTransaction indicates that the annotated void method should be executed after a transaction is ended for test methods configured to run within a transaction via Spring’s @Transactional annotation. As of Spring Framework 4.3, @AfterTransaction methods are not required to be public and may be declared on Java 8 based interface default methods.

@Sql is used to annotate a test class or test method to configure SQL scripts to be executed against a given database during integration tests.

@SqlConfig

@SqlConfig defines metadata that is used to determine how to parse and execute SQL scripts configured via the @Sql annotation.

@SqlGroup

@SqlGroup is a container annotation that aggregates several @Sql annotations. @SqlGroup can be used natively, declaring several nested @Sql annotations, or it can be used in conjunction with Java 8’s support for repeatable annotations, where @Sql can simply be declared several times on the same class or method, implicitly generating this container annotation.

15.4.2 Standard Annotation Support

The following annotations are supported with standard semantics for all configurations of the Spring TestContext Framework. Note that these annotations are not specific to tests and can be used anywhere in the Spring Framework.

In the Spring TestContext Framework @PostConstruct and @PreDestroy may be used with standard semantics on any application components configured in the ApplicationContext ; however, these lifecycle annotations have limited usage within an actual test class.

15.4.3 Spring JUnit 4 Testing Annotations

The following annotations are only supported when used in conjunction with the SpringRunner, Spring’s JUnit rules, or Spring’s JUnit 4 support classes.

@IfProfileValue

@IfProfileValue can be applied at the class level, the method level, or both. Class-level usage of @IfProfileValue takes precedence over method-level usage for any methods within that class or its subclasses. Specifically, a test is enabled if it is enabled both at the class level and at the method level; the absence of @IfProfileValue means the test is implicitly enabled. This is analogous to the semantics of JUnit 4’s @Ignore annotation, except that the presence of @Ignore always disables a test.

Alternatively, you can configure @IfProfileValue with a list of values (with OR semantics) to achieve TestNG-like support for test groups in a JUnit 4 environment. Consider the following example:

@ProfileValueSourceConfiguration

@ProfileValueSourceConfiguration is a class-level annotation that specifies what type of ProfileValueSource to use when retrieving profile values configured through the @IfProfileValue annotation. If @ProfileValueSourceConfiguration is not declared for a test, SystemProfileValueSource is used by default.

@Timed

@Timed indicates that the annotated test method must finish execution in a specified time period (in milliseconds). If the text execution time exceeds the specified time period, the test fails.

The time period includes execution of the test method itself, any repetitions of the test (see @Repeat ), as well as any set up or tear down of the test fixture.

Читайте также:  что делает соцработник на дому

@Repeat

@Repeat indicates that the annotated test method must be executed repeatedly. The number of times that the test method is to be executed is specified in the annotation.

The scope of execution to be repeated includes execution of the test method itself as well as any set up or tear down of the test fixture.

15.4.4 Meta-Annotation Support for Testing

It is possible to use most test-related annotations as meta-annotations in order to create custom composed annotations and reduce configuration duplication across a test suite.

Each of the following may be used as meta-annotations in conjunction with the TestContext framework.

For example, if we discover that we are repeating the following configuration across our JUnit 4 based test suite…​

We can reduce the above duplication by introducing a custom composed annotation that centralizes the common test configuration like this:

Then we can use our custom @TransactionalDevTest annotation to simplify the configuration of individual test classes as follows:

15.5 Spring TestContext Framework

The Spring TestContext Framework (located in the org.springframework.test.context package) provides generic, annotation-driven unit and integration testing support that is agnostic of the testing framework in use. The TestContext framework also places a great deal of importance on convention over configuration with reasonable defaults that can be overridden through annotation-based configuration.

The following section provides an overview of the internals of the TestContext framework. If you are only interested in using the framework and not necessarily interested in extending it with your own custom listeners or custom loaders, feel free to go directly to the configuration (context management, dependency injection, transaction management), support classes, and annotation support sections.

15.5.1 Key abstractions

TestContext

TestContext encapsulates the context in which a test is executed, agnostic of the actual testing framework in use, and provides context management and caching support for the test instance for which it is responsible. The TestContext also delegates to a SmartContextLoader to load an ApplicationContext if requested.

TestContextManager

TestExecutionListener

TestExecutionListener defines the API for reacting to test execution events published by the TestContextManager with which the listener is registered. See Section 15.5.3, “TestExecutionListener configuration”.

Context Loaders

ContextLoader is a strategy interface that was introduced in Spring 2.5 for loading an ApplicationContext for an integration test managed by the Spring TestContext Framework. Implement SmartContextLoader instead of this interface in order to provide support for annotated classes, active bean definition profiles, test property sources, context hierarchies, and WebApplicationContext support.

Spring provides the following implementations:

15.5.2 Bootstrapping the TestContext framework

Since the TestContextBootstrapper SPI is likely to change in the future in order to accommodate new requirements, implementers are strongly encouraged not to implement this interface directly but rather to extend AbstractTestContextBootstrapper or one of its concrete subclasses instead.

15.5.3 TestExecutionListener configuration

Spring provides the following TestExecutionListener implementations that are registered by default, exactly in this order.

Registering custom TestExecutionListeners

Custom TestExecutionListener s can be registered for a test class and its subclasses via the @TestExecutionListeners annotation. See annotation support and the javadocs for @TestExecutionListeners for details and examples.

Automatic discovery of default TestExecutionListeners

Registering custom TestExecutionListener s via @TestExecutionListeners is suitable for custom listeners that are used in limited testing scenarios; however, it can become cumbersome if a custom listener needs to be used across a test suite. Since Spring Framework 4.1, this issue is addressed via support for automatic discovery of default TestExecutionListener implementations via the SpringFactoriesLoader mechanism.

Specifically, the spring-test module declares all core default TestExecutionListener s under the org.springframework.test.context.TestExecutionListener key in its META-INF/spring.factories properties file. Third-party frameworks and developers can contribute their own TestExecutionListener s to the list of default listeners in the same manner via their own META-INF/spring.factories properties file.

Ordering TestExecutionListeners

Merging TestExecutionListeners

The challenge with this approach is that it requires that the developer know exactly which listeners are registered by default. Moreover, the set of default listeners can change from release to release — for example, SqlScriptsTestExecutionListener was introduced in Spring Framework 4.1, and DirtiesContextBeforeModesTestExecutionListener was introduced in Spring Framework 4.2. Furthermore, third-party frameworks like Spring Security register their own default TestExecutionListener s via the aforementioned automatic discovery mechanism.

15.5.4 Context management

As an alternative to implementing the ApplicationContextAware interface, you can inject the application context for your test class through the @Autowired annotation on either a field or setter method. For example:

Dependency injection via @Autowired is provided by the DependencyInjectionTestExecutionListener which is configured by default (see Section 15.5.5, “Dependency injection of test fixtures”).

The following sections explain how to configure an ApplicationContext via XML configuration files, Groovy scripts, annotated classes (typically @Configuration classes), or context initializers using Spring’s @ContextConfiguration annotation. Alternatively, you can implement and configure your own custom SmartContextLoader for advanced use cases.

Context configuration with XML resources

Context configuration with Groovy scripts

To load an ApplicationContext for your tests using Groovy scripts that utilize the Groovy Bean Definition DSL, annotate your test class with @ContextConfiguration and configure the locations or value attribute with an array that contains the resource locations of Groovy scripts. Resource lookup semantics for Groovy scripts are the same as those described for XML configuration files.

Support for using Groovy scripts to load an ApplicationContext in the Spring TestContext Framework is enabled automatically if Groovy is on the classpath.

The following listing demonstrates how to combine both in an integration test.

Context configuration with annotated classes

To load an ApplicationContext for your tests using annotated classes (see Section 7.12, “Java-based container configuration”), annotate your test class with @ContextConfiguration and configure the classes attribute with an array that contains references to annotated classes.

The term annotated class can refer to any of the following.

If you omit the classes attribute from the @ContextConfiguration annotation, the TestContext framework will attempt to detect the presence of default configuration classes. Specifically, AnnotationConfigContextLoader and AnnotationConfigWebContextLoader will detect all static nested classes of the test class that meet the requirements for configuration class implementations as specified in the @Configuration javadocs. In the following example, the OrderServiceTest class declares a static nested configuration class named Config that will be automatically used to load the ApplicationContext for the test class. Note that the name of the configuration class is arbitrary. In addition, a test class can contain more than one static nested configuration class if desired.

Mixing XML, Groovy scripts, and annotated classes

It may sometimes be desirable to mix XML configuration files, Groovy scripts, and annotated classes (i.e., typically @Configuration classes) to configure an ApplicationContext for your tests. For example, if you use XML configuration in production, you may decide that you want to use @Configuration classes to configure specific Spring-managed components for your tests, or vice versa.

Context configuration with context initializers

It is also possible to omit the declaration of XML configuration files, Groovy scripts, or annotated classes in @ContextConfiguration entirely and instead declare only ApplicationContextInitializer classes which are then responsible for registering beans in the context — for example, by programmatically loading bean definitions from XML files or configuration classes.

Context configuration inheritance

Context configuration with environment profiles

Spring 3.1 introduced first-class support in the framework for the notion of environments and profiles (a.k.a., bean definition profiles ), and integration tests can be configured to activate particular bean definition profiles for various testing scenarios. This is achieved by annotating a test class with the @ActiveProfiles annotation and supplying a list of profiles that should be activated when loading the ApplicationContext for the test.

@ActiveProfiles may be used with any implementation of the new SmartContextLoader SPI, but @ActiveProfiles is not supported with implementations of the older ContextLoader SPI.

Let’s take a look at some examples with XML configuration and @Configuration classes.

When TransferServiceTest is run, its ApplicationContext will be loaded from the app-config.xml configuration file in the root of the classpath. If you inspect app-config.xml you’ll notice that the accountRepository bean has a dependency on a dataSource bean; however, dataSource is not defined as a top-level bean. Instead, dataSource is defined three times: in the production profile, the dev profile, and the default profile.

It is sometimes useful to assign beans to a default profile. Beans within the default profile are only included when no other profile is specifically activated. This can be used to define fallback beans to be used in the application’s default state. For example, you may explicitly provide a data source for dev and production profiles, but define an in-memory data source as a default when neither of these is active.

The following code listings demonstrate how to implement the same configuration and integration test but using @Configuration classes instead of XML.

In this variation, we have split the XML configuration into four independent @Configuration classes:

@ActiveProfiles also supports an inheritProfiles attribute that can be used to disable the inheritance of active profiles.

Furthermore, it is sometimes necessary to resolve active profiles for tests programmatically instead of declaratively — for example, based on:

Context configuration with test property sources

@TestPropertySource may be used with any implementation of the SmartContextLoader SPI, but @TestPropertySource is not supported with implementations of the older ContextLoader SPI.

Declaring test property sources

Test properties files can be configured via the locations or value attribute of @TestPropertySource as shown in the following example.

Inlined properties in the form of key-value pairs can be configured via the properties attribute of @TestPropertySource as shown in the following example. All key-value pairs will be added to the enclosing Environment as a single test PropertySource with the highest precedence.

The supported syntax for key-value pairs is the same as the syntax defined for entries in a Java properties file:

Default properties file detection

Precedence

Test property sources have higher precedence than those loaded from the operating system’s environment or Java system properties as well as property sources added by the application declaratively via @PropertySource or programmatically. Thus, test property sources can be used to selectively override properties defined in system and application property sources. Furthermore, inlined properties have higher precedence than properties loaded from resource locations.

In the following example, the timezone and port properties as well as any properties defined in «/test.properties» will override any properties of the same name that are defined in system and application property sources. Furthermore, if the «/test.properties» file defines entries for the timezone and port properties those will be overridden by the inlined properties declared via the properties attribute.

Inheriting and overriding test property sources

In the following example, the ApplicationContext for BaseTest will be loaded using only the «base.properties» file as a test property source. In contrast, the ApplicationContext for ExtendedTest will be loaded using the «base.properties» and «extended.properties» files as test property source locations.

In the following example, the ApplicationContext for BaseTest will be loaded using only the inlined key1 property. In contrast, the ApplicationContext for ExtendedTest will be loaded using the inlined key1 and key2 properties.

Loading a WebApplicationContext

Default resource semantics.

Explicit resource semantics.

In this third example, we see that we can override the default resource semantics for both annotations by specifying a Spring resource prefix. Contrast the comments in this example with the previous example.

Context caching

An ApplicationContext can be uniquely identified by the combination of configuration parameters that are used to load it. Consequently, the unique combination of configuration parameters are used to generate a key under which the context is cached. The TestContext framework uses the following configuration parameters to build the context cache key:

The Spring TestContext framework stores application contexts in a static cache. This means that the context is literally stored in a static variable. In other words, if tests execute in separate processes the static cache will be cleared between each test execution, and this will effectively disable the caching mechanism.

In the unlikely case that a test corrupts the application context and requires reloading — for example, by modifying a bean definition or the state of an application object — you can annotate your test class or test method with @DirtiesContext (see the discussion of @DirtiesContext in Section 15.4.1, “Spring Testing Annotations”). This instructs Spring to remove the context from the cache and rebuild the application context before executing the next test. Note that support for the @DirtiesContext annotation is provided by the DirtiesContextBeforeModesTestExecutionListener and the DirtiesContextTestExecutionListener which are enabled by default.

Context hierarchies

Since Spring Framework 3.2.2, it is possible to write integration tests that use context hierarchies by declaring context configuration via the @ContextHierarchy annotation, either on an individual test class or within a test class hierarchy. If a context hierarchy is declared on multiple classes within a test class hierarchy it is also possible to merge or override the context configuration for a specific, named level in the context hierarchy. When merging configuration for a given level in the hierarchy the configuration resource type (i.e., XML configuration files or annotated classes) must be consistent; otherwise, it is perfectly acceptable to have different levels in a context hierarchy configured using different resource types.

The following JUnit 4 based examples demonstrate common configuration scenarios for integration tests that require the use of context hierarchies.

ControllerIntegrationTests represents a typical integration testing scenario for a Spring MVC web application by declaring a context hierarchy consisting of two levels, one for the root WebApplicationContext (loaded using the TestAppConfig @Configuration class) and one for the dispatcher servlet WebApplicationContext (loaded using the WebConfig @Configuration class). The WebApplicationContext that is autowired into the test instance is the one for the child context (i.e., the lowest context in the hierarchy).

If @DirtiesContext is used in a test whose context is configured as part of a context hierarchy, the hierarchyMode flag can be used to control how the context cache is cleared. For further details consult the discussion of @DirtiesContext in Spring Testing Annotations and the @DirtiesContext javadocs.

15.5.5 Dependency injection of test fixtures

The TestContext framework does not instrument the manner in which a test instance is instantiated. Thus the use of @Autowired or @Inject for constructors has no effect for test classes.

Consider the scenario of testing a HibernateTitleRepository class, as outlined in the Goals section. The next two code listings demonstrate the use of @Autowired on fields and setter methods. The application context configuration is presented after all sample code listings.

The dependency injection behavior in the following code listings is not specific to JUnit 4. The same DI techniques can be used in conjunction with any testing framework.

The first code listing shows a JUnit 4 based implementation of the test class that uses @Autowired for field injection.

Alternatively, you can configure the class to use @Autowired for setter injection as seen below.

The preceding code listings use the same XML context file referenced by the @ContextConfiguration annotation (that is, repository-config.xml ), which looks like this:

If you are extending from a Spring-provided test base class that happens to use @Autowired on one of its setter methods, you might have multiple beans of the affected type defined in your application context: for example, multiple DataSource beans. In such a case, you can override the setter method and use the @Qualifier annotation to indicate a specific target bean as follows, but make sure to delegate to the overridden method in the superclass as well.

The specified qualifier value indicates the specific DataSource bean to inject, narrowing the set of type matches to a specific bean. Its value is matched against declarations within the corresponding definitions. The bean name is used as a fallback qualifier value, so you may effectively also point to a specific bean by name there (as shown above, assuming that «myDataSource» is the bean id).

15.5.6 Testing request and session scoped beans

Request and session scoped beans have been supported by Spring since the early years, and since Spring 3.2 it’s a breeze to test your request-scoped and session-scoped beans by following these steps.

The following code snippet displays the XML configuration for a login use case. Note that the userService bean has a dependency on a request-scoped loginAction bean. Also, the LoginAction is instantiated using SpEL expressions that retrieve the username and password from the current HTTP request. In our test, we will want to configure these request parameters via the mock managed by the TestContext framework.

Request-scoped bean configuration.

Request-scoped bean test.

The following code snippet is similar to the one we saw above for a request-scoped bean; however, this time the userService bean has a dependency on a session-scoped userPreferences bean. Note that the UserPreferences bean is instantiated using a SpEL expression that retrieves the theme from the current HTTP session. In our test, we will need to configure a theme in the mock session managed by the TestContext framework.

Session-scoped bean configuration.

Session-scoped bean test.

15.5.7 Transaction management

In the TestContext framework, transactions are managed by the TransactionalTestExecutionListener which is configured by default, even if you do not explicitly declare @TestExecutionListeners on your test class. To enable support for transactions, however, you must configure a PlatformTransactionManager bean in the ApplicationContext that is loaded via @ContextConfiguration semantics (further details are provided below). In addition, you must declare Spring’s @Transactional annotation either at the class or method level for your tests.

Test-managed transactions

Test-managed transactions are transactions that are managed declaratively via the TransactionalTestExecutionListener or programmatically via TestTransaction (see below). Such transactions should not be confused with Spring-managed transactions (i.e., those managed directly by Spring within the ApplicationContext loaded for tests) or application-managed transactions (i.e., those managed programmatically within application code that is invoked via tests). Spring-managed and application-managed transactions will typically participate in test-managed transactions; however, caution should be taken if Spring-managed or application-managed transactions are configured with any propagation type other than REQUIRED or SUPPORTS (see the discussion on transaction propagation for details).

Enabling and disabling transactions

Transaction rollback and commit behavior

By default, test transactions will be automatically rolled back after completion of the test; however, transactional commit and rollback behavior can be configured declaratively via the @Commit and @Rollback annotations. See the corresponding entries in the annotation support section for further details.

Programmatic transaction management

Executing code outside of a transaction

Occasionally you need to execute certain code before or after a transactional test method but outside the transactional context — for example, to verify the initial database state prior to execution of your test or to verify expected transactional commit behavior after test execution (if the test was configured to commit the transaction). TransactionalTestExecutionListener supports the @BeforeTransaction and @AfterTransaction annotations exactly for such scenarios. Simply annotate any void method in a test class or any void default method in a test interface with one of these annotations, and the TransactionalTestExecutionListener ensures that your before transaction method or after transaction method is executed at the appropriate time.

Any before methods (such as methods annotated with JUnit 4’s @Before ) and any after methods (such as methods annotated with JUnit 4’s @After ) are executed within a transaction. In addition, methods annotated with @BeforeTransaction or @AfterTransaction are naturally not executed for test methods that are not configured to run within a transaction.

Configuring a transaction manager

Demonstration of all transaction-related annotations

The following JUnit 4 based example displays a fictitious integration testing scenario highlighting all transaction-related annotations. The example is not intended to demonstrate best practices but rather to demonstrate how these annotations can be used. Consult the annotation support section for further information and configuration examples. Transaction management for @Sql contains an additional example using @Sql for declarative SQL script execution with default transaction rollback semantics.

15.5.8 Executing SQL scripts

When writing integration tests against a relational database, it is often beneficial to execute SQL scripts to modify the database schema or insert test data into tables. The spring-jdbc module provides support for initializing an embedded or existing database by executing SQL scripts when the Spring ApplicationContext is loaded. See Section 19.8, “Embedded database support” and Section 19.8.5, “Testing data access logic with an embedded database” for details.

Although it is very useful to initialize a database for testing once when the ApplicationContext is loaded, sometimes it is essential to be able to modify the database during integration tests. The following sections explain how to execute SQL scripts programmatically and declaratively during integration tests.

Executing SQL scripts programmatically

Spring provides the following options for executing SQL scripts programmatically within integration test methods.

ScriptUtils provides a collection of static utility methods for working with SQL scripts and is mainly intended for internal use within the framework. However, if you require full control over how SQL scripts are parsed and executed, ScriptUtils may suit your needs better than some of the other alternatives described below. Consult the javadocs for individual methods in ScriptUtils for further details.

Note that ResourceDatabasePopulator internally delegates to ScriptUtils for parsing and executing SQL scripts. Similarly, the executeSqlScript(..) methods in AbstractTransactionalJUnit4SpringContextTests and AbstractTransactionalTestNGSpringContextTests internally use a ResourceDatabasePopulator for executing SQL scripts. Consult the javadocs for the various executeSqlScript(..) methods for further details.

Executing SQL scripts declaratively with @Sql

Path resource semantics

The following example demonstrates how to use @Sql at the class level and at the method level within a JUnit 4 based integration test class.

Default script detection

If no SQL scripts are specified, an attempt will be made to detect a default script depending on where @Sql is declared. If a default cannot be detected, an IllegalStateException will be thrown.

Declaring multiple @Sql sets

The following example demonstrates the use of @Sql as a repeatable annotation using Java 8. In this scenario the test-schema.sql script uses a different syntax for single-line comments.

The following example is identical to the above except that the @Sql declarations are grouped together within @SqlGroup for compatibility with Java 6 and Java 7.

Script execution phases

By default, SQL scripts will be executed before the corresponding test method. However, if a particular set of scripts needs to be executed after the test method — for example, to clean up database state — the executionPhase attribute in @Sql can be used as seen in the following example. Note that ISOLATED and AFTER_TEST_METHOD are statically imported from Sql.TransactionMode and Sql.ExecutionPhase respectively.

Script configuration with @SqlConfig

The configuration options provided by @Sql and @SqlConfig are equivalent to those supported by ScriptUtils and ResourceDatabasePopulator but are a superset of those provided by the XML namespace element. Consult the javadocs of individual attributes in @Sql and @SqlConfig for details.

Transaction management for @Sql

Источник

Читайте также:  что делать если котенок потерялся на даче
Сказочный портал
Declaring XML config and Groovy scripts simultaneously