From 6431b2504596b27fa6268ea744ba7b699bb2d73c Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Tue, 18 Sep 2018 15:43:14 +0200 Subject: [PATCH] Revise Testing chapter for technical correctness This commit also fixes some broken links and typos. --- src/docs/asciidoc/testing.adoc | 121 +++++++++++++++++---------------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/src/docs/asciidoc/testing.adoc b/src/docs/asciidoc/testing.adoc index f51ba6c7a7a..cf92e6a313e 100644 --- a/src/docs/asciidoc/testing.adoc +++ b/src/docs/asciidoc/testing.adoc @@ -236,8 +236,7 @@ instrumentation of tests in various environments, including JUnit, TestNG, and o Spring's integration testing support has the following primary goals: -* To manage <> between test - runs. +* To manage <> between tests. * To provide <>. * To provide <> appropriate to integration testing. * To supply <> that assist @@ -268,7 +267,7 @@ 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 +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 @@ -499,12 +498,12 @@ The following example shows such a case: <1> Declaring an initializer class. ==== -You can optionally use `@ContextConfiguration` to declare the `ContextLoader` strategy -as well. Note, however, that you typically do not need to explicitly configure the -loader, since the default loader supports resource `locations`, annotated -`classes`, and `initializers`. +You can optionally use `@ContextConfiguration` to declare the `ContextLoader` strategy as +well. Note, however, that you typically do not need to explicitly configure the loader, +since the default loader supports `initializers` and either resource `locations` or +annotated `classes`. -The following example uses both a location and a class: +The following example uses both a location and a loader: ==== [source,java,indent=0] @@ -519,7 +518,7 @@ The following example uses both a location and a class: ==== NOTE: `@ContextConfiguration` provides support for inheriting resource locations or -configuration classes as well as context initializers that are, by default, declared by superclasses. +configuration classes as well as context initializers that are declared by superclasses. See <> and the `@ContextConfiguration` javadocs for further details. @@ -556,7 +555,7 @@ The following example shows how to use the `@WebAppConfiguration` annotation: To override the default, you can specify a different base resource path by using 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. -The following example shows how to specify a classpath: +The following example shows how to specify a classpath resource: ==== [source,java,indent=0] @@ -568,7 +567,7 @@ The following example shows how to specify a classpath: // class body... } ---- -<1> Specifying a classpath. +<1> Specifying a classpath resource. ==== Note that `@WebAppConfiguration` must be used in conjunction with @@ -696,7 +695,7 @@ The following example demonstrates how to declare a properties file from the cla // class body... } ---- -<1> Get properties from `test.properties`. +<1> Get properties from `test.properties` in the root of the classpath. ==== The following example demonstrates how to declare inlined properties: @@ -746,7 +745,7 @@ configuration scenarios: // some tests that require a new Spring container } ---- -<1> Dirty the context before the current class. +<1> Dirty the context before the current test class. ==== * After the current test class, when declared on a class with class mode set to @@ -761,7 +760,7 @@ configuration scenarios: // some tests that result in the Spring container being dirtied } ---- -<1> Dirty the context after the current class. +<1> Dirty the context after the current test class. ==== * Before each test method in the current test class, when declared on a class with class @@ -807,7 +806,7 @@ mode set to `AFTER_EACH_TEST_METHOD.` // some logic that requires a new Spring container } ---- -<1> Dirty the context before a method. +<1> Dirty the context before the current test method. ==== * After the current test, when declared on a method with the method mode set to @@ -823,7 +822,7 @@ mode set to `AFTER_EACH_TEST_METHOD.` // some logic that results in the Spring container being dirtied } ---- -<1> Dirty the context after a method. +<1> Dirty the context after the current test method. ==== If you use `@DirtiesContext` in a test whose context is configured as part of a context @@ -873,7 +872,7 @@ For further details regarding the `EXHAUSTIVE` and `CURRENT_LEVEL` algorithms, s `TestContextManager`. Typically, `@TestExecutionListeners` is used in conjunction with `@ContextConfiguration`. -The following example shows how to define two `TestExecutionListener` implementations: +The following example shows how to register two `TestExecutionListener` implementations: ==== [source,java,indent=0] @@ -885,7 +884,7 @@ The following example shows how to define two `TestExecutionListener` implementa // class body... } ---- -<1> Define two `TestExecutionListener` implementations. +<1> Register two `TestExecutionListener` implementations. ==== By default, `@TestExecutionListeners` supports inherited listeners. See the {api-spring-framework}/test/context/TestExecutionListeners.html[Javadoc] @@ -946,7 +945,7 @@ result is committed to the database): // ... } ---- -<1> Do not roll back the result +<1> Do not roll back the result. ==== @@ -1210,7 +1209,7 @@ The following example shows how to use it: [source,java,indent=0] [subs="verbatim,quotes"] ---- - @Timed(millis=1000) <1> + @Timed(millis = 1000) <1> public void testProcessWithOneSecondTimeout() { // some logic that should not take longer than 1 second to execute } @@ -1937,7 +1936,7 @@ on either a field or setter method, as the following example shows: // class body... } ---- -<1> Autowiring a field. +<1> Injecting the `ApplicationContext`. ==== Similarly, if your test is configured to load a `WebApplicationContext`, you can inject @@ -1951,13 +1950,15 @@ the web application context into your test, as follows: @WebAppConfiguration <1> @ContextConfiguration public class MyWebAppTest { - **@Autowired** + + @Autowired <2> private WebApplicationContext wac; // class body... } ---- -<1> Injecting the `WebApplicationContext`. +<1> Configuring the `WebApplicationContext`. +<2> Injecting the `WebApplicationContext`. ==== Dependency injection by using `@Autowired` is provided by the @@ -1974,9 +1975,9 @@ how to load a context from a default location or default configuration classes. addition to context resource locations and annotated classes, an application context can also be configured through application context initializers. -The following sections explain how to configure an `ApplicationContext` by using XML -configuration files, Groovy scripts, annotated classes (typically `@Configuration` -classes), or context initializers that use Spring's `@ContextConfiguration` annotation. +The following sections explain how to use Spring's `@ContextConfiguration` annotation to +configure a test `ApplicationContext` by using XML configuration files, Groovy scripts, +annotated classes (typically `@Configuration` classes), or context initializers. Alternatively, you can implement and configure your own custom `SmartContextLoader` for advanced use cases. @@ -2175,10 +2176,10 @@ The following example shows how to do so: .Annotated Classes [TIP] ==== -The term, "`annotated class,`" can refer to any of the following: +The term "`annotated class`" can refer to any of the following: * A class annotated with `@Configuration`. -* A component (that, a class annotated with `@Component`, `@Service`, `@Repository`, and others). +* A component (that is, a class annotated with `@Component`, `@Service`, `@Repository`, or other stereotype annotations). * A JSR-330 compliant class that is annotated with `javax.inject` annotations. * Any other class that contains `@Bean` methods. @@ -2260,7 +2261,7 @@ framework, you have the following options. If you want to use resource locations (for example, XML or Groovy) and `@Configuration` classes to configure your tests, you must pick one as the entry point, and that one must include or import the other. For example, in XML or Groovy scripts, -you can include `@Configuration` classes by using component scanning or define them as normal +you can include `@Configuration` classes by using component scanning or defining them as normal Spring beans, whereas, in a `@Configuration` class, you can use `@ImportResource` to import XML configuration files or Groovy scripts. Note that this behavior is semantically equivalent to how you configure your application in production: In production @@ -2297,7 +2298,7 @@ or the standard `@Priority` annotation. The following example shows how to use i // class body... } ---- -<1> Loading configuration with an initializer. +<1> Specifying configuration by using a configuration class and an initializer. ==== You can also omit the declaration of XML configuration files, Groovy scripts, @@ -2318,7 +2319,7 @@ files or configuration classes. The following example shows how to do so: // class body... } ---- -<1> Specifying configuration by using only an initializer class. +<1> Specifying configuration by using only an initializer. ==== @@ -2433,7 +2434,7 @@ initializer and the superclass's initializer: [[testcontext-ctx-management-env-profiles]] -===== Context Configuration with environment profiles +===== Context Configuration with Environment Profiles Spring 3.1 introduced first-class support in the framework for the notion of environments and profiles (AKA "`bean definition profiles`"), and integration tests @@ -2804,7 +2805,7 @@ Each path is interpreted as a Spring `Resource`. A plain path (for example, `"test.properties"`) is treated as a classpath resource that is relative to the package in which the test class is defined. A path starting with a slash is treated as an absolute classpath resource (for example: `"/org/example/test.xml"`). A path that -references a URL (for example, a path prefixed with `classpath:`, `file:`, `http:`, and others) +references a URL (for example, a path prefixed with `classpath:`, `file:`, or `http:`) is loaded by using the specified resource protocol. Resource location wildcards (such as `**/*.properties`) are not permitted: Each location must evaluate to exactly one `.properties` or `.xml` resource. @@ -2937,7 +2938,7 @@ by using `properties` files: In the next example, the `ApplicationContext` for `BaseTest` is loaded by using only the inlined `key1` property. In contrast, the `ApplicationContext` for `ExtendedTest` is -loaded by using the inlined_`key1` and `key2` properties. The following example shows how +loaded by using the inlined `key1` and `key2` properties. The following example shows how to define properties in both a subclass and its superclass by using inline properties: ==== @@ -3088,7 +3089,7 @@ Once you have a `WebApplicationContext` loaded for your test, you might find tha need to interact with the web mocks -- for example, to set up your test fixture or to perform assertions after invoking your web component. The following example shows which mocks can be autowired into your test instance. Note that the -`WebApplicationContext` and `MockServletContext` are both cached across the test suite +`WebApplicationContext` and `MockServletContext` are both cached across the test suite, whereas the other mocks are managed per test method by the `ServletTestExecutionListener`. @@ -4082,7 +4083,7 @@ Each path is interpreted as a Spring `Resource`. A plain path (for example, `"schema.sql"`) is treated as a classpath resource that is relative to the package in which the test class is defined. A path starting with a slash is treated as an absolute classpath resource (for example, `"/org/example/schema.sql"`). A path -that references a URL (for example, a path prefixed with `classpath:`, `file:`, `http:`, and others) +that references a URL (for example, a path prefixed with `classpath:`, `file:`, `http:`) is loaded by using the specified resource protocol. The following example shows how to use `@Sql` at the class level and at the method @@ -4236,7 +4237,7 @@ By default, the `SqlScriptsTestExecutionListener` infers the desired transaction semantics for scripts configured by using `@Sql`. Specifically, SQL scripts are run without a transaction, within an existing Spring-managed transaction (for example, a transaction managed by the `TransactionalTestExecutionListener` for a test annotated with -`@Transactional`) or within an isolated transaction, depending on the configured value +`@Transactional`), or within an isolated transaction, depending on the configured value of the `transactionMode` attribute in `@SqlConfig` and the presence of a `PlatformTransactionManager` in the test's `ApplicationContext`. As a bare minimum, however, a `javax.sql.DataSource` must be present in the test's `ApplicationContext`. @@ -4800,7 +4801,7 @@ to load Spring configuration from an XML configuration file located in the same as the test class, but Java-based and Groovy-based configuration are also supported. See these https://github.com/spring-projects/spring-framework/tree/master/spring-test/src/test/java/org/springframework/test/web/servlet/samples/context[sample tests]. -The MockMvc instance is used to perform a `GET` request to `/accounts/1` and verify +The `MockMvc` instance is used to perform a `GET` request to `/accounts/1` and verify that the resulting response has status 200, the content type is `application/json`, and the response body has a JSON property called `name` with the value `Lee`. The `jsonPath` syntax is supported through the Jayway https://github.com/jayway/JsonPath[JsonPath @@ -4827,10 +4828,10 @@ completion on static members. [[spring-mvc-test-server-setup-options]] ===== Setup Choices -You have two main options for creating an instance of MockMvc. +You have two main options for creating an instance of `MockMvc`. The first is to load Spring MVC configuration through the TestContext framework, which loads the Spring configuration and injects a `WebApplicationContext` -into the test to use to build a MockMvc instance. The following example shows how to do so: +into the test to use to build a `MockMvc` instance. The following example shows how to do so: ==== [source,java,indent=0] @@ -5072,7 +5073,7 @@ properties, as the following example shows: ---- ==== -The preceding properties affect every request performed through the MockMvc instance. +The preceding properties affect every request performed through the `MockMvc` instance. If the same property is also specified on a given request, it overrides the default value. That is why the HTTP method and URI in the default request do not matter, since they must be specified on every request. @@ -5157,7 +5158,7 @@ other expectations, as the following example shows: ==== If all tests repeat the same expectations, you can set up common expectations once -when building the MockMvc instance, as the following example shows: +when building the `MockMvc` instance, as the following example shows: ==== [source,java,indent=0] @@ -5171,7 +5172,7 @@ when building the MockMvc instance, as the following example shows: ==== Note that common expectations are always applied and cannot be overridden without -creating a separate MockMvc instance. +creating a separate `MockMvc` instance. When a JSON response content contains hypermedia links created with https://github.com/spring-projects/spring-hateoas[Spring HATEOAS], you can verify the resulting links @@ -5205,7 +5206,7 @@ by using XPath expressions: [[spring-mvc-test-server-filters]] ===== Filter Registrations -When setting up a MockMvc instance, you can register one or more Servlet `Filter` instances, +When setting up a `MockMvc` instance, you can register one or more Servlet `Filter` instances, as the following example shows: ==== @@ -5495,10 +5496,10 @@ We can easily create an HtmlUnit `WebClient` that integrates with MockMvc by usi ==== NOTE: This is a simple example of using `MockMvcWebClientBuilder`. For advanced usage, see -<> +<>. This ensures that any URL that references `localhost` as the server is directed to -our MockMvc instance without the need for a real HTTP connection. Any other URL is +our `MockMvc` instance without the need for a real HTTP connection. Any other URL is requested by using a network connection, as normal. This lets us easily test the use of CDNs. @@ -5519,7 +5520,7 @@ a message with the following: ==== NOTE: The default context path is `""`. Alternatively, we can specify the context path, as -described in <>. +described in <>. Once we have a reference to the `HtmlPage`, we can then fill out the form and submit it to create a message, as the following example shows: @@ -5613,7 +5614,7 @@ We can also specify additional configuration options, as the following example s ---- ==== -As an alternative, we can perform the exact same setup by configuring the MockMvc +As an alternative, we can perform the exact same setup by configuring the `MockMvc` instance separately and supplying it to the `MockMvcWebClientBuilder`, as follows: ==== @@ -5635,10 +5636,10 @@ instance separately and supplying it to the `MockMvcWebClientBuilder`, as follow ---- ==== -This is more verbose, but, by building the `WebClient` with a MockMvc instance, we have +This is more verbose, but, by building the `WebClient` with a `MockMvc` instance, we have the full power of MockMvc at our fingertips. -TIP: For additional information on creating a MockMvc instance, see +TIP: For additional information on creating a `MockMvc` instance, see <>. @@ -5779,7 +5780,7 @@ NOTE: This is a simple example of using `MockMvcHtmlUnitDriverBuilder`. For more advanced usage, see <>. The preceding example ensures that any URL that references `localhost` as the server is directed to -our MockMvc instance without the need for a real HTTP connection. Any other URL is +our `MockMvc` instance without the need for a real HTTP connection. Any other URL is requested by using a network connection, as normal. This lets us easily test the use of CDNs. @@ -5865,7 +5866,7 @@ up by the `id` or `name` of the element within the HTML page. <3> We can use the https://github.com/SeleniumHQ/selenium/wiki/PageFactory#making-the-example-work-using-annotations[`@FindBy` annotation] to override the default lookup behavior. Our example shows how to use the `@FindBy` -annotation to look up our submit button with a css selector (*input[type=submit]*). +annotation to look up our submit button with a `css` selector (*input[type=submit]*). ==== Finally, we can verify that a new message was created successfully. The following @@ -5898,7 +5899,7 @@ model. For example, it exposes a method that returns a `Message` object: We can then use the rich domain objects in our assertions. -Lastly, we must not forget to close the WebDriver instance when the test is complete, as follows: +Lastly, we must not forget to close the `WebDriver` instance when the test is complete, as follows: ==== [source,java,indent=0] @@ -5921,7 +5922,7 @@ https://github.com/SeleniumHQ/selenium/wiki/Getting-Started[WebDriver documentat ====== Advanced `MockMvcHtmlUnitDriverBuilder` In the examples so far, we have used `MockMvcHtmlUnitDriverBuilder` in the simplest way -possible, by building a WebDriver based on the `WebApplicationContext` loaded for us by +possible, by building a `WebDriver` based on the `WebApplicationContext` loaded for us by the Spring TestContext Framework. This approach is repeated here, as follows: ==== @@ -5963,7 +5964,7 @@ We can also specify additional configuration options, as follows: ---- ==== -As an alternative, we can perform the exact same setup by configuring the MockMvc +As an alternative, we can perform the exact same setup by configuring the `MockMvc` instance separately and supplying it to the `MockMvcHtmlUnitDriverBuilder`, as follows: ==== @@ -5985,10 +5986,10 @@ instance separately and supplying it to the `MockMvcHtmlUnitDriverBuilder`, as f ---- ==== -This is more verbose, but, by building the WebDriver with a MockMvc instance, we have +This is more verbose, but, by building the `WebDriver` with a `MockMvc` instance, we have the full power of MockMvc at our fingertips. -TIP: For additional information on creating a MockMvc instance, see +TIP: For additional information on creating a `MockMvc` instance, see <>. @@ -6032,7 +6033,7 @@ NOTE: This is a simple example of using `MockMvcHtmlUnitDriverBuilder`. For more advanced usage, see <>. This ensures that any URL referencing `localhost` as the server is directed to -our MockMvc instance without the need for a real HTTP connection. Any other URL is +our `MockMvc` instance without the need for a real HTTP connection. Any other URL is requested by using a network connection as normal. This lets us easily test the use of CDNs. @@ -6216,7 +6217,7 @@ but, aside from that subsequent "/something" and "/somewhere", requests can come As an alternative to all of the above, the client-side test support also provides a `ClientHttpRequestFactory` implementation that you can configure into a `RestTemplate` -to bind it to a MockMvc instance. That allows processing requests using actual +to bind it to a `MockMvc` instance. That allows processing requests using actual server-side logic but without running a server. The following example shows how to do so: ==== @@ -6339,7 +6340,7 @@ The following listing shows the definition of the `HibernateClinicTests` class: @ContextConfiguration <1> public class HibernateClinicTests extends AbstractClinicTests { } ---- -<1> Load the application context from the default location: `AbstractClinicTests-context.xml`. +<1> Load the application context from `AbstractClinicTests-context.xml` and `HibernateClinicTests-context.xml`. ==== In a large-scale application, the Spring configuration is often split across multiple