diff --git a/spring-boot-docs/src/main/asciidoc/index.adoc b/spring-boot-docs/src/main/asciidoc/index.adoc index 8a6c8323280..ae64dce7150 100644 --- a/spring-boot-docs/src/main/asciidoc/index.adoc +++ b/spring-boot-docs/src/main/asciidoc/index.adoc @@ -23,11 +23,15 @@ Phillip Webb; Dave Syer; Josh Long; Stéphane Nicoll; Rob Winch; Andy Wilkinson; :sc-spring-boot-actuator: {github-code}/spring-boot-actuator/src/main/java/org/springframework/boot/actuate :sc-spring-boot-cli: {github-code}/spring-boot-cli/src/main/java/org/springframework/boot/cli :sc-spring-boot-devtools: {github-code}/spring-boot-devtools/src/main/java/org/springframework/boot/devtools +:sc-spring-boot-test: {github-code}/spring-boot-test/src/main/java/org/springframework/boot/test +:sc-spring-boot-test-autoconfigure: {github-code}/spring-boot-test/src/main/java/org/springframework/boot/test/autoconfigure :dc-ext: html :dc-root: http://docs.spring.io/spring-boot/docs/{spring-boot-docs-version}/api :dc-spring-boot: {dc-root}/org/springframework/boot :dc-spring-boot-autoconfigure: {dc-root}/org/springframework/boot/autoconfigure :dc-spring-boot-actuator: {dc-root}/org/springframework/boot/actuate +:dc-spring-boot-test: {dc-root}/spring-boot-test/src/main/java/org/springframework/boot/test +:dc-spring-boot-test-autoconfigure: {dc-root}/spring-boot-test/src/main/java/org/springframework/boot/test/autoconfigure :dependency-management-plugin: https://github.com/spring-gradle-plugins/dependency-management-plugin :dependency-management-plugin-documentation: {dependency-management-plugin}/blob/master/README.md :spring-boot-maven-plugin-site: http://docs.spring.io/spring-boot/docs/{spring-boot-docs-version}/maven-plugin diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index a31fa695b78..0ec238270b9 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -4161,10 +4161,13 @@ class for more details. [[boot-features-testing]] == Testing -Spring Boot provides a number of useful tools for testing your application. The -`spring-boot-starter-test` POM provides Spring Test, JUnit, Hamcrest and Mockito -dependencies. There are also useful test utilities in the core `spring-boot` module under -the `org.springframework.boot.test` package. +Spring Boot provides a number of utilities and annotations to help when testing your +application. Test support is provided by two modules; `spring-boot-test` contains core +items, and `spring-boot-test-autoconfigure` supports auto-configuration for tests. + +Most developers will just use the the `spring-boot-starter-test` '`Starter POM`' which +imports both Spring Boot test modules as well has JUnit, AssertJ, Hamcrest and a number +of other useful libraries. @@ -4174,16 +4177,21 @@ If you use the `spring-boot-starter-test` '`Starter POM`' (in the `test` `scope`), you will find the following provided libraries: -* Spring Test -- integration test support for Spring applications. -* JUnit -- The de-facto standard for unit testing Java applications. -* Hamcrest -- A library of matcher objects (also known as constraints or predicates) - allowing `assertThat` style JUnit assertions. -* Mockito -- A Java mocking framework. +* http://junit.org[JUnit] -- The de-facto standard for unit testing Java applications. +* {spring-reference}/#integration-testing.html[Spring Test] & Spring Boot Test -- utilties and integration test support for Spring Boot + applications. +* http://joel-costigliola.github.io/assertj/[AssertJ] - A fluent assertion library. +* http://hamcrest.org/JavaHamcrest/[Hamcrest] -- A library of matcher objects (also known + as constraints or predicates). +* http://mockito.org/[Mockito] -- A Java mocking framework. +* https://github.com/skyscreamer/JSONassert[JSONassert] -- An assertion library for JSON. +* https://github.com/jayway/JsonPath[JsonPath] -- XPath for JSON. These are common libraries that we generally find useful when writing tests. You are free to add additional test dependencies of your own if these don't suit your needs. + [[boot-features-testing-spring-applications]] === Testing Spring applications One of the major advantages of dependency injection is that it should make your code @@ -4207,100 +4215,484 @@ documentation. [[boot-features-testing-spring-boot-applications]] === Testing Spring Boot applications -A Spring Boot application is just a Spring `ApplicationContext` so nothing very special +A Spring Boot application is just a Spring `ApplicationContext`, so nothing very special has to be done to test it beyond what you would normally do with a vanilla Spring context. One thing to watch out for though is that the external properties, logging and other features of Spring Boot are only installed in the context by default if you use `SpringApplication` to create it. -Spring Boot provides a `@SpringApplicationConfiguration` annotation as an alternative -to the standard `spring-test` `@ContextConfiguration` annotation. If you use -`@SpringApplicationConfiguration` to configure the `ApplicationContext` used in your -tests, it will be created via `SpringApplication` and you will get the additional Spring -Boot features. +Spring Boot provides three annotations which can be used as an alternative the standard +`spring-test` `@ContextConfiguration` annotation when you need Spring Boot features. All +three work by creating the `ApplicationContext` used in your tests via +`SpringApplication`. -For example: -[source,java,indent=0,subs="verbatim,quotes,attributes"] +The specific annotation that you choose will depend on the type of test that you are writing: + +* `@SpringApplicationTest` -- Loads an `ApplicationContext` or `WebApplicationContext` + (depending on your classpath) using `SpringApplication` and provides a mock servlet environment. Embedded servlet containers are not started + when using this annotation. +* `@WebIntegrationTest` -- Loads an `EmbeddedWebApplicationContext` using + `SpringApplication` and provides a real servlet environment. Embedded servlet containers + are started and listening on a defined or random port. +* `@IntegrationTest` -- Loads an `ApplicationContext` using `SpringApplication` but does + not provides _any_ servlet environment (mock or otherwise). + +NOTE: In addition to `@SpringApplicationTest`, `@WebIntegrationTest` and +`@IntegrationTest` a number of other annotations are also provided for testing more +specific slices of an application. See below for details. + +TIP: Don't forget to also add `@RunWith(SpringRunner.class)` to your test, otherwise +the annotations will be ignored. + + + +[[boot-features-testing-spring-boot-applications-detecting-config]] +==== Detecting configuration +If you're familiar with the Spring Test Framework, you may be used to using +`@ContextConfiguration(classes=...)` in order to specify which Spring `@Configuration` +to load. Alternatively, you might have often used nested `@Configuration` classes within +your test. + +When testing Spring Boot applications this is often not required. +Spring Boot's `@*Test` annotations will search for your primary configuration automatically +whenever you don't explicitly defined one. + +The search algorithm works up from the package that contains the test until it finds a +`@SpringBootApplication` or `@SpringBootConfiguration` annotated class. As long as you've +<> in a sensible way your main +configuration is usually found. + +NOTE: Spring's test framework will cache application contexts between tests. Therefore, as +long as your tests share the same configuration (no matter how it's discovered), the +potentially time consuming process of loading the context will only happen once. + + + +[[boot-features-testing-spring-boot-applications-excluding-config]] +==== Excluding test configuration +If your application uses component scanning, for example if you use +`@SpringBootApplication` or `@ComponentScan`, you may find components or configurations +created only for specific tests accidentally get picked up everywhere. + +To help prevent this, Spring Boot provides `@TestComponent` and `@TestConfiguration` +annotations that can be used on classes in `src/test/java` to indicate that they should +not be picked up by scanning. + +NOTE: `@TestComponent` and `@TestConfiguration` are only needed on top level classes. If +you define `@Configuration` or `@Component` as inner-classes within a test, they will be +automatically filtered. + +NOTE: If you directly use `@ComponentScan` (i.e. not via `@SpringBootApplication`) you +will need to register the `TypeExcludeFilter` with it. See +{dc-spring-boot}/context/TypeExcludeFilter.{dc-ext}[the Javadoc] for details. + + + +[[boot-features-testing-spring-boot-applications-using-springapplicationtest]] +==== Using @SpringApplicationTest +Use the `@SpringApplicationTest` annotation to load a `ApplicationContext` or +`WebApplicationContext` via `SpringApplication` and configure it with a mock +servlet environment. Embedded servlet containers will not be started when using +`@SpringApplicationTest`. + +A `WebApplicationContext` is created when Servlet API jars are present on your +classpath. If you're developing a non-web application, the regular +`ApplicationContext` is used. + +The `@Configuration` classes to load can either be explicitly defined using +`@ContextConfiguration`, specified as inner-classes or +<> + +[source,java,indent=0] ---- - @RunWith(SpringJUnit4ClassRunner.class) - @SpringApplicationConfiguration(SampleDataJpaApplication.class) - public class CityRepositoryIntegrationTests { + import org.junit.*; + import org.junit.runner.*; + import org.springframework.beans.factory.annotation.*; + import org.springframework.boot.test.context.*; + import org.springframework.test.context.junit4.*; + + @RunWith(SpringRunner.class) + @SpringApplicationTest + public class MySpringApplicationTests { @Autowired - CityRepository repository; + private MyComponent component; - // ... + // ... tests } ---- -TIP: The context loader guesses whether you want to test a web application or not (e.g. -with `MockMvc`) by looking for the `@WebIntegrationTest` or `@WebAppConfiguration` -annotations. (`MockMvc` and `@WebAppConfiguration` are part of `spring-test`). -If you want a web application to start up and listen on its normal port, so you can test -it with HTTP (e.g. using `RestTemplate`), annotate your test class (or one of its -superclasses) with `@WebIntegrationTest`. This can be very useful because it means you can -test the full stack of your application, but also inject its components into the test -class and use them to assert the internal state of the application after an HTTP -interaction. For example: -[source,java,indent=0,subs="verbatim,quotes,attributes"] +[[boot-features-testing-spring-boot-applications-using-webintegrationtest]] +==== Using @WebIntegrationTest +Use the `@WebIntegrationTest` annotation to load a `WebApplicationContext` via +`SpringApplication` and configure it with fully running server listening on the appropriate +port. + +The `@Configuration` classes to load can either be explicitly defined using +`@ContextConfiguration`, specified as inner-classes or +<> + +For convenience, tests that need to make REST calls to the started server can additionally +`@Autowire` a `TestRestTemplate` which will resolve relative links to the running server. + +To change the port you can add environment properties to `@WebIntegrationTest` as colon- +or equals-separated name-value pairs, e.g. `@WebIntegrationTest("server.port:9000")`. +Additionally you can set the `server.port` and `management.port` properties to `0` +or use the `randomPort` attribute in order to run your integration tests using +random ports. + +[source,java,indent=0] ---- - @RunWith(SpringJUnit4ClassRunner.class) - @SpringApplicationConfiguration(SampleDataJpaApplication.class) - @WebIntegrationTest - public class CityRepositoryIntegrationTests { + import org.junit.*; + import org.junit.runner.*; + import org.springframework.boot.test.context.web.*; + import org.springframework.boot.test.web.client.*; + import org.springframework.test.context.junit4.*; + + import static org.assertj.core.api.Assertions.* + + @RunWith(SpringRunner.class) + @WebIntegrationTest(randomPort=true) + public class MyWebIntegrationTests { @Autowired - CityRepository repository; + private TestRestTemplate restTemplate; + + @Test + public void exampleTest() { + String body = this.restTemplate.getForObject("/", String.class); + assertThat(body).isEqualTo("Hello World"); + } + + } +---- + +See <> for a description of how you can discover +the actual port that was allocated for the duration of the tests if you're not using the +injected `TestRestTemplate`. + - RestTemplate restTemplate = new TestRestTemplate(); - // ... interact with the running server +[[boot-features-testing-spring-boot-applications-using-integrationtest]] +==== Using @IntegrationTest +Use the `@IntegrationTest` annotation to load an `ApplicationContext` via +`SpringApplication` for non web-applications. Mock servlet support is explicitly disabled +for tests annotated with `@IntegrationTest`. + +The `@Configuration` classes to load can either be explicitly defined using +`@ContextConfiguration`, specified as inner-classes or +<> + +[source,java,indent=0] +---- + import org.junit.*; + import org.junit.runner.*; + import org.springframework.beans.factory.annotation.*; + import org.springframework.boot.test.context.*; + import org.springframework.test.context.junit4.*; + + @RunWith(SpringRunner.class) + @IntegrationTest + public class MyIntegrationTests { + + @Autowired + private MyComponent component; + + // ... tests } ---- -NOTE: Spring's test framework will cache application contexts between tests. Therefore, -as long as your tests share the same configuration, the time consuming process of starting -and stopping the server will only happen once, regardless of the number of tests that -actually run. +NOTE: Although it's possible to use the `@WebAppConfiguration` annotation in combination +with `@IntegrationTest` if you want to start a full web server, the `@WebIntegrationTest` +annotation is generally preferable. -To change the port you can add environment properties to `@WebIntegrationTest` as colon- -or equals-separated name-value pairs, e.g. `@WebIntegrationTest("server.port:9000")`. -Additionally you can set the `server.port` and `management.port` properties to `0` -in order to run your integration tests using random ports. For example: -[source,java,indent=0,subs="verbatim,quotes,attributes"] + +[[boot-features-testing-spring-boot-applications-mocking-beans]] +==== Mocking Beans +It's sometimes necessary to mock certain components within your application context when +running tests. For example, you may have a facade over some remote service that's +unavailable during development. Mocking can also be useful when you want to simulate +failures that might be hard to trigger in a real environment. + +Spring Boot includes a `@MockBean` annotation that can be used to define a Mockito mock +for a bean inside your `ApplicationContext`. You can use the annotation to add new beans, +or replace a single existing bean definition. The annotation can be used directly on test +classes, on fields within your test; or on `@Configuration` classes and fields. When used +on a field the, instance of the created mock will also be injected. Mock beans are +automatically reset after each test method. + +Here's a typical example where we replace an existing `RemoteService` bean with a mock +implementation: + +[source,java,indent=0] ---- - @RunWith(SpringJUnit4ClassRunner.class) - @SpringApplicationConfiguration(MyApplication.class) - @WebIntegrationTest({"server.port=0", "management.port=0"}) - public class SomeIntegrationTests { + import org.junit.*; + import org.junit.runner.*; + import org.springframework.beans.factory.annotation.*; + import org.springframework.boot.test.context.*; + import org.springframework.boot.test.mock.mockito.*; + import org.springframework.test.context.junit4.*; - // ... + import static org.assertj.core.api.Assertions.*; + import static org.mockito.BDDMockito.*; + + @RunWith(SpringRunner.class) + @SpringApplicationTest + public class MyTests { + + @MockBean + private RemoteService remoteService; + + @Autowired + private Reverser reverser; + + @Test + public void exampleTest() { + // RemoteService has been injected into the reverser bean + given(this.remoteService.someCall()).willReturn("mock"); + String reverse = reverser.reverseSomeCall(); + assertThat(reverse).isEqualTo("kcom"); + } } ---- -Alternatively, you can use the `randomPort` convenience attribute to set `server.port=0`. -For example: -[source,java,indent=0,subs="verbatim,quotes,attributes"] + +[[boot-features-testing-spring-boot-applications-testing-autoconfigured-tests]] +==== Auto-configured tests +Spring Boot's auto-configuration system works well for applications, but can sometimes be +a little too much for tests. It's often helpful to load only the parts of the +configuration that are required to test a '`slice`' of your application. For example, you +might want to test that Spring MVC controllers are mapping URLs correctly, and you don't +want to involve and database calls in those tests; or you _might be wanting_ to test JPA +entites, and you're not interested in web layer when those tests run. + +The `spring-boot-test-autoconfigure` module includes a number of annotations that can be +used to automatically configure such '`slices`'. Each of them work in a similar way, +providing a `@...Test` annotation that loads the `ApplicationContext` and one or +more `@AutoConfigure...` annotations that can be used to customize auto-configuration +settings. + +TIP: It's also possible to use the `@AutoConfigure...` annotations with the standard +`@SpringApplicationTest` annotation. You can use this combination if you're not interested + in '`slicing`' your application but you want some of the auto-configured test beans. + + + +[[boot-features-testing-spring-boot-applications-testing-autoconfigured-json-tests]] +==== Auto-configured JSON tests +To test that Object JSON serilization and deserialization is working as expected you can +use the `@JsonTest` annotation. `@JsonTest` will auto-configure Jackson ObjectMappers, +any `@JsonComponent` beans and any Jackson `Modules`. It also configures `Gson` +if you happen to be using that instead of, or as well as, Jackson. If you need to +configure elements of the auto-configuration you can use the `@AutoConfigureJsonTesters` +annotation. + +Spring Boot includes AssertJ based helpers that work with the JSONassert and JsonPath +libraries to check that JSON is as expected. The `JacksonHelper`, `GsonHelper` and +`BasicJsonHelper` classes can be used for Jackson, Gson and Strings respectively. Any +helper fields on the test class will be automatically initialized when using `@JsonTest`. + +[source,java,indent=0] ---- - @RunWith(SpringJUnit4ClassRunner.class) - @SpringApplicationConfiguration(MyApplication.class) - @WebIntegrationTest(randomPort = true) - public class SomeIntegrationTests { + import org.junit.*; + import org.junit.runner.*; + import org.springframework.boot.test.autoconfigure.json.*; + import org.springframework.boot.test.context.*; + import org.springframework.boot.test.json.*; + import org.springframework.test.context.junit4.*; + + import static org.assertj.core.api.Assertions.*; + + @RunWith(SpringRunner.class) + @JsonTest + public class MyJsonTests { + + private JacksonTester json; + + @Test + public void testSerialize() throws Exception { + VehicleDetails details = new VehicleDetails("Honda", "Civic"); + // Assert against a `.json` file in the same package as the test + assertThat(this.json.write(details)).isEqualToJson("expected.json"); + // Or use JSON path based assertions + assertThat(this.json.write(details)).hasJsonPathStringValue("@.make"); + assertThat(this.json.write(details)).extractingJsonPathStringValue("@.make") + .isEqualTo("Honda"); + } - // ... + @Test + public void testDeserialize() throws Exception { + String content = "{\"make\":\"Ford\",\"model\":\"Focus\"}"; + assertThat(this.json.parse(content)) + .isEqualTo(new VehicleDetails("Ford", "Focus")); + assertThat(this.json.parseObject(content).getMake()).isEqualTo("Ford"); + } } ---- -See <> for a description of how you can discover -the actual port that was allocated for the duration of the tests. + +NOTE: JSON helper classes can also be used directly in standard unit tests. Simply +call the `initFields` method of the helper in your `@Before` method if you aren't using +`@JsonTest`. + + + +[[boot-features-testing-spring-boot-applications-testing-autoconfigured-mvc-tests]] +==== Auto-configured Spring MVC tests +To test Spring MVC controllers are working as expected you can use the `@WebMvcTest` +annotation. `@WebMvcTest` will auto-configure the Spring MVC infrastructure and limit +scanned beans to `@Controller`, `@ControllerAdvice`, `@JsonComponent`, `Filter`, +`WebMvcConfigurer` and `HandlerMethodArgumentResolver`. Regular `@Component` beans +will not be scanned when using this annotation. + +Often `@WebMvcTest` will be limited to a single controller and used in combination with +`@MockBean` to provide mock implementations for required collaborators. + +`@WebMvcTest` is meta-annotated with `@AutoConfigureMockMvc` which provides +auto-configuration of `MockMvc`. Mock MVC offers a powerful way to quickly test MVC +controllers without needing to start a full HTTP server. + +[source,java,indent=0] +---- + import org.junit.*; + import org.junit.runner.*; + import org.springframework.beans.factory.annotation.*; + import org.springframework.boot.test.autoconfigure.web.servlet.*; + import org.springframework.boot.test.mock.mockito.*; + + import static org.assertj.core.api.Assertions.*; + import static org.mockito.BDDMockito.*; + import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; + import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + + @RunWith(SpringRunner.class) + @WebMvcTest(UserVehicleController.class) + public class MyControllerTests { + + @Autowired + private MockMvc mvc; + + @MockBean + private UserVehicleService userVehicleService; + + @Test + public void testExample() throws Exception { + given(this.userVehicleService.getVehicleDetails("sboot")) + .willReturn(new VehicleDetails("Honda", "Civic")); + this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN)) + .andExpect(status().isOk()).andExpect(content().string("Honda Civic")); + } + + } +---- + +TIP: If you need to configure elements of the auto-configuration (for example when servlet +filters should be applied) you can use attributes in the `@AutoConfigureJsonTesters` annotation. + +If you use HtmlUnit or Selenium, auto-configuration will also provide a `WebClient` bean +and/or a `WebDriver` bean. Here is an example that uses HtmlUnit: + + +[source,java,indent=0] +---- + import com.gargoylesoftware.htmlunit.*; + import org.junit.*; + import org.junit.runner.*; + import org.springframework.beans.factory.annotation.*; + import org.springframework.boot.test.autoconfigure.web.servlet.*; + import org.springframework.boot.test.mock.mockito.*; + + import static org.assertj.core.api.Assertions.*; + import static org.mockito.BDDMockito.*; + + @RunWith(SpringRunner.class) + @WebMvcTest(UserVehicleController.class) + public class MyHtmlUnitTests { + + @Autowired + private WebClient webClient; + + @MockBean + private UserVehicleService userVehicleService; + + @Test + public void testExample() throws Exception { + given(this.userVehicleService.getVehicleDetails("sboot")) + .willReturn(new VehicleDetails("Honda", "Civic")); + HtmlPage page = this.webClient.getPage("/sboot/vehicle.html"); + assertThat(page.getBody().getTextContent()).isEqualTo("Honda Civic"); + } + + } +---- + + + +[[boot-features-testing-spring-boot-applications-testing-autoconfigured-jpa-test]] +==== Auto-configured Data JPA tests +The `@DataJpaTest` can be used if want to test JPA applications. By default it will +configure an in-memory embedded database, scan for `@Entity` classes and configure Spring +Data JPA repositories. Regular `@Component` beans will not be loaded into the +`ApplicationContext`. + +Data JPA tests may also inject a +{sc-spring-boot-test-autoconfigure}/orm/jpa/TestEntityManager.{sc-ext}[`TestEntityManager`] +bean which provides an alternative to the standard JPA `EntityManager` specifically +designed for tests. If you want to use `TestEntityManager` outside of `@DataJpaTests` you +can also use the `@AutoConfigureTestEntityManager` annotation. + +[source,java,indent=0] +---- + import org.junit.*; + import org.junit.runner.*; + import org.springframework.boot.test.autoconfigure.orm.jpa.*; + + import static org.assertj.core.api.Assertions.*; + + @RunWith(SpringRunner.class) + @DataJpaTest + public class ExampleRepositoryTests { + + @Autowired + private TestEntityManager entityManager; + + @Autowired + private UserRepository repository; + + @Test + public void testExample() throws Exception { + this.entityManager.persist(new User("sboot", "1234")); + User user = this.repository.findByUsername("sboot"); + assertThat(user.getUsername()).isEqualTo("sboot"); + assertThat(user.getVin()).isEqualTo("1234"); + } + + } +---- + +In-memory embedded databases generally work well for tests since they are fast and don't +require any developer installation. If, however, you prefer to run tests against a real +database you can use the `@AutoConfigureTestDatabase` annotation: + +[source,java,indent=0] +---- + @RunWith(SpringRunner.class) + @DataJpaTest + @AutoConfigureTestDatabase(replace=Replace.NONE) + public class ExampleRepositoryTests { + + // ... + + } +---- @@ -4327,7 +4719,7 @@ useful when testing your application. ==== ConfigFileApplicationContextInitializer `ConfigFileApplicationContextInitializer` is an `ApplicationContextInitializer` that can apply to your tests to load Spring Boot `application.properties` files. You can use -this when you don't need the full features provided by `@SpringApplicationConfiguration`. +this when you don't need the full features provided by `@SpringApplicationTest`. [source,java,indent=0] ---- @@ -4360,7 +4752,7 @@ for assertions: ---- import org.junit.Rule; import org.junit.Test; -import org.springframework.boot.test.OutputCapture; +import org.springframework.boot.test.rule.OutputCapture; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; @@ -4381,7 +4773,6 @@ public class MyTest { [[boot-features-rest-templates-test-utility]] ==== TestRestTemplate - `TestRestTemplate` is a convenience subclass of Spring's `RestTemplate` that is useful in integration tests. You can get a vanilla template or one that sends Basic HTTP authentication (with a username and password). In either case the template will behave