|
| 1 | +# Pact Spring7/Spring Boot4 + JUnit5 Support |
| 2 | + |
| 3 | +This module extends the base [Pact JUnit5 module](/provider/junit5/README.md) (See that for more details) and adds support |
| 4 | +for Spring 7 and Spring Boot 4. |
| 5 | + |
| 6 | +**NOTE: This module requires JDK 17+** |
| 7 | + |
| 8 | +## Dependency |
| 9 | +The combined library (JUnit5 + Spring7) is available on maven central using: |
| 10 | + |
| 11 | +group-id = au.com.dius.pact.provider |
| 12 | +artifact-id = spring7 |
| 13 | +version-id = 4.5.x |
| 14 | + |
| 15 | +## Usage |
| 16 | +For writing Spring Pact verification tests with JUnit 5, there is an JUnit 5 Invocation Context Provider that you can use with |
| 17 | +the `@TestTemplate` annotation. This will generate a test for each interaction found for the pact files for the provider. |
| 18 | + |
| 19 | +To use it, add the `@Provider` and `@ExtendWith(SpringExtension.class)` or `@SpringbootTest` and one of the pact source |
| 20 | +annotations to your test class (as per a JUnit 5 test), then add a method annotated with `@TestTemplate` and |
| 21 | +`@ExtendWith(PactVerificationSpring7Provider.class)` that takes a `PactVerificationContext` parameter. You will need to |
| 22 | +call `verifyInteraction()` on the context parameter in your test template method. |
| 23 | + |
| 24 | +For example: |
| 25 | + |
| 26 | +```java |
| 27 | +@AutoConfigureMockMvc |
| 28 | +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) |
| 29 | +@Provider("Animal Profile Service") |
| 30 | +@PactBroker |
| 31 | +public class ContractVerificationTest { |
| 32 | + |
| 33 | + @TestTemplate |
| 34 | + @ExtendWith(PactVerificationSpring7Provider.class) |
| 35 | + void pactVerificationTestTemplate(PactVerificationContext context) { |
| 36 | + context.verifyInteraction(); |
| 37 | + } |
| 38 | + |
| 39 | +} |
| 40 | +``` |
| 41 | + |
| 42 | +You will now be able to setup all the required properties using the Spring context, e.g. creating an application |
| 43 | +YAML file in the test resources: |
| 44 | + |
| 45 | +```yaml |
| 46 | +pactbroker: |
| 47 | + host: your.broker.host |
| 48 | + auth: |
| 49 | + username: broker-user |
| 50 | + password: broker.password |
| 51 | +``` |
| 52 | +
|
| 53 | +You can also run pact tests against `MockMvc` without need to spin up the whole application context which takes time |
| 54 | +and often requires more additional setup (e.g. database). In order to run lightweight tests just use `@WebMvcTest` |
| 55 | +from Spring and `Spring7MockMvcTestTarget` as a test target before each test. |
| 56 | + |
| 57 | +For example: |
| 58 | +```java |
| 59 | +@WebMvcTest |
| 60 | +@Provider("myAwesomeService") |
| 61 | +@PactBroker |
| 62 | +class ContractVerificationTest { |
| 63 | + |
| 64 | + @Autowired |
| 65 | + private MockMvc mockMvc; |
| 66 | +
|
| 67 | + @TestTemplate |
| 68 | + @ExtendWith(PactVerificationSpring7Provider.class) |
| 69 | + void pactVerificationTestTemplate(PactVerificationContext context) { |
| 70 | + context.verifyInteraction(); |
| 71 | + } |
| 72 | + |
| 73 | + @BeforeEach |
| 74 | + void before(PactVerificationContext context) { |
| 75 | + context.setTarget(new Spring7MockMvcTestTarget(mockMvc)); |
| 76 | + } |
| 77 | +} |
| 78 | +``` |
| 79 | + |
| 80 | +You can also use `Spring7MockMvcTestTarget` for tests without spring context by providing the controllers manually. |
| 81 | + |
| 82 | +For example: |
| 83 | +```java |
| 84 | +@Provider("myAwesomeService") |
| 85 | +@PactFolder("pacts") |
| 86 | +class MockMvcTestTargetStandaloneMockMvcTestJava { |
| 87 | +
|
| 88 | + @TestTemplate |
| 89 | + @ExtendWith(PactVerificationSpring7Provider.class) |
| 90 | + void pactVerificationTestTemplate(PactVerificationContext context) { |
| 91 | + context.verifyInteraction(); |
| 92 | + } |
| 93 | +
|
| 94 | + @BeforeEach |
| 95 | + void before(PactVerificationContext context) { |
| 96 | + Spring7MockMvcTestTarget testTarget = new Spring7MockMvcTestTarget(); |
| 97 | + testTarget.setControllers(new DataResource()); |
| 98 | + context.setTarget(testTarget); |
| 99 | + } |
| 100 | +
|
| 101 | + @RestController |
| 102 | + static class DataResource { |
| 103 | + @GetMapping("/data") |
| 104 | + @ResponseStatus(HttpStatus.NO_CONTENT) |
| 105 | + void getData(@RequestParam("ticketId") String ticketId) { |
| 106 | + } |
| 107 | + } |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +**Important:** Since `@WebMvcTest` starts only Spring MVC components you can't use `PactVerificationSpring7Provider` |
| 112 | +and need to fallback to `PactVerificationInvocationContextProvider` |
| 113 | + |
| 114 | +## Webflux tests |
| 115 | + |
| 116 | +You can test Webflux routing functions using the `WebFluxSpring7Target` target class. The easiest way to do it is to get Spring to |
| 117 | +autowire your handler and router into the test and then pass the routing function to the target. |
| 118 | + |
| 119 | +For example: |
| 120 | + |
| 121 | +```java |
| 122 | + @Autowired |
| 123 | + YourRouter router; |
| 124 | +
|
| 125 | + @Autowired |
| 126 | + YourHandler handler; |
| 127 | +
|
| 128 | + @BeforeEach |
| 129 | + void setup(PactVerificationContext context) { |
| 130 | + context.setTarget(new WebFluxSpring7Target(router.route(handler))); |
| 131 | + } |
| 132 | +
|
| 133 | + @TestTemplate |
| 134 | + @ExtendWith(PactVerificationSpring7Provider.class) |
| 135 | + void pactVerificationTestTemplate(PactVerificationContext context) { |
| 136 | + context.verifyInteraction(); |
| 137 | + } |
| 138 | +``` |
| 139 | + |
| 140 | +## Modifying requests |
| 141 | + |
| 142 | +As documented in [Pact JUnit5 module](/provider/junit5/README.md#modifying-the-requests-before-they-are-sent), you can |
| 143 | +inject a request object to modify the requests made. However, depending on the Pact test target you are using, |
| 144 | +you need to use a different class. |
| 145 | + |
| 146 | +| Test Target | Class to use | |
| 147 | +|-----------------------------------------------|----------------------------------| |
| 148 | +| HttpTarget, HttpsTarget, SpringBootHttpTarget | org.apache.http.HttpRequest | |
| 149 | +| Spring7MockMvcTestTarget | MockHttpServletRequestBuilder | |
| 150 | +| WebFluxSpring7Target | WebTestClient.RequestHeadersSpec | |
| 151 | + |
| 152 | +# Verifying V4 Pact files that require plugins |
| 153 | + |
| 154 | +Pact files that require plugins can be verified with version 4.3.0+. For details on how plugins work, see the |
| 155 | +[Pact plugin project](https://github.com/pact-foundation/pact-plugins). |
| 156 | + |
| 157 | +Each required plugin is defined in the `plugins` section in the Pact metadata in the Pact file. The plugins will be |
| 158 | +loaded from the plugin directory. By default, this is `~/.pact/plugins` or the value of the `PACT_PLUGIN_DIR` environment |
| 159 | +variable. Each plugin required by the Pact file must be installed there. You will need to follow the installation |
| 160 | +instructions for each plugin, but the default is to unpack the plugin into a sub-directory `<plugin-name>-<plugin-version>` |
| 161 | +(i.e., for the Protobuf plugin 0.0.0 it will be `protobuf-0.0.0`). The plugin manifest file must be present for the |
| 162 | +plugin to be able to be loaded. |
| 163 | + |
| 164 | +# Test Analytics |
| 165 | + |
| 166 | +We are tracking anonymous analytics to gather important usage statistics like JVM version |
| 167 | +and operating system. To disable tracking, set the 'pact_do_not_track' system property or environment |
| 168 | +variable to 'true'. |
0 commit comments