[[integration-testing]]
= Integration Testing

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

* The correct wiring of your Spring IoC container contexts.
* Data access using JDBC or an ORM tool. This can include such things as the correctness
  of SQL statements, Hibernate queries, JPA entity mappings, and so forth.

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 <<core.adoc#beans-dependencies, 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.

Unit and integration testing support is provided in the form of the annotation-driven
<<testcontext-framework, Spring TestContext Framework>>. The TestContext framework is
agnostic of the actual testing framework in use, which allows instrumentation of tests
in various environments, including JUnit, TestNG, and others.

The following section provides an overview of the high-level goals of Spring's
integration support, and the rest of this chapter then focuses on dedicated topics:

* <<integration-testing-support-jdbc>>
* <<testcontext-framework>>
* <<webtestclient>>
* <<spring-mvc-test-framework>>
* <<spring-mvc-test-client>>
* <<integration-testing-annotations>>



[[integration-testing-goals]]
== Goals of Integration Testing

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

* To manage <<testing-ctx-management, Spring IoC container caching>> between tests.
* To provide <<testing-fixture-di, Dependency Injection of test fixture instances>>.
* To provide <<testing-tx, transaction management>> appropriate to integration testing.
* To supply <<testing-support-classes, Spring-specific base classes>> that assist
  developers in writing integration tests.

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


[[testing-ctx-management]]
=== Context Management and Caching

The Spring TestContext Framework provides consistent loading of Spring
`ApplicationContext` instances and `WebApplicationContext` instances 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 component 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.

See <<testcontext-ctx-management>> and <<testcontext-ctx-management-caching>> with the
TestContext framework.


[[testing-fixture-di]]
=== Dependency Injection of Test Fixtures

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

As an example, consider a scenario where we have a class (`HibernateTitleRepository`)
that implements data access logic for a `Title` domain entity. We want to write
integration tests that test the following areas:

* The Spring configuration: Basically, is everything related to the configuration of the
  `HibernateTitleRepository` bean correct and present?
* The Hibernate mapping file configuration: Is everything mapped correctly and are the
  correct lazy-loading settings in place?
* The logic of the `HibernateTitleRepository`: Does the configured instance of this class
  perform as anticipated?

See dependency injection of test fixtures with the
<<testcontext-fixture-di, TestContext framework>>.


[[testing-tx]]
=== 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 use 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 of a transaction.

The TestContext framework addresses this issue. By default, the framework creates and
rolls back a transaction for each test. You can write code that can assume the existence
of a transaction. If you call transactionally proxied objects in your tests, they 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 rolls back by default, and the database returns to
its state prior to execution of the test. Transactional support is provided to a test by
using 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), you can tell the TestContext
framework to cause the transaction to commit instead of roll back by using the
<<integration-testing-annotations, `@Commit`>> annotation.

See transaction management with the <<testcontext-tx, TestContext framework>>.


[[testing-support-classes]]
=== 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 let you access:

* The `ApplicationContext`, for performing explicit bean lookups or testing the state of
  the context as a whole.
* A `JdbcTemplate`, for executing SQL statements to query the database. You can use such
  queries to confirm database state both before and after execution of database-related
  application code, and Spring ensures that such queries run in the scope of the same
  transaction as the application code. When used in conjunction with an ORM tool, be sure
  to avoid <<testcontext-tx-false-positives, false positives>>.

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-support-classes, TestContext framework>>.
