6
6
[ ![ Twitter Follow] ( https://img.shields.io/twitter/follow/skuzzleOSS.svg?style=social )] ( https://twitter.com/skuzzleOSS )
7
7
8
8
# spring-boot-wiremock
9
- (This is ** not** an official extension from the Spring Team!)
9
+ _ This is ** not** an official extension from the Spring Team!_ (Though one exists as part of the
10
+ [ spring-cloud] ( https://cloud.spring.io/spring-cloud-contract/reference/html/project-features.html#features-wiremock )
11
+ project).
10
12
11
- The easiest way to setup a [ WireMock] ( http://wiremock.org/ ) server in your Spring-Boot tests with * JUnit5 *
13
+ The easiest way to setup a [ WireMock] ( http://wiremock.org/ ) server in your Spring-Boot tests.
12
14
- [x] Run WireMock server on random port
13
15
- [x] Inject WireMock hosts (http and https) as spring application property
14
16
- [x] Easily setup server- and client side SSL
15
- - [x] Define simple stubs using annotations
17
+ - [x] Declarative stubs using annotations
16
18
17
19
``` xml
18
20
<dependency >
19
21
<groupId >de.skuzzle.springboot.test</groupId >
20
22
<artifactId >spring-boot-wiremock</artifactId >
21
- <version >0.0.12 </version >
23
+ <version >0.0.13 </version >
22
24
<scope >test</scope >
23
25
</dependency >
24
26
```
@@ -66,6 +68,10 @@ Injecting the host into the application context happens _before_ any bean instan
66
68
property values takes precedence over any other, for example statically configured value. This means, in most cases the
67
69
extension works out of the box with your current context configuration.
68
70
71
+ You can see more annotation stubbing examples in
72
+ [ this] ( https://github.com/skuzzle/spring-boot-wiremock/blob/main/src/test/java/de/skuzzle/springboot/test/wiremock/TestHttpStub.java )
73
+ test class.
74
+
69
75
## Rationale
70
76
[ WireMock] ( http://wiremock.org/ ) is an awesome library for mocking HTTP endpoints in unit tests. However, it can be
71
77
quite cumbersome to integrate with Spring-Boot: when you manually manage the ` WireMockServer ` from within the test,
@@ -84,17 +90,166 @@ can be injected into the Spring application properties, simply replacing an exis
84
90
85
91
## Compatibility
86
92
- [x] Requires Java 11
87
- - [x] Tested against Spring-Boot ` 2.2.13.RELEASE, 2.3.12.RELEASE, 2.4.7 , 2.5.2 `
93
+ - [x] Tested against Spring-Boot ` 2.2.13.RELEASE, 2.3.12.RELEASE, 2.4.8 , 2.5.2 `
88
94
- [x] Tested against WireMock ` 2.27.1 `
89
95
96
+ ## Usage
97
+
98
+ ### WireMock based stubbing
99
+ If you set up WireMock using ` @WithWireMock ` the server instance is made available as bean in the Spring
100
+ ` ApplicationContext ` . It can thus be injected into the test class like this:
101
+
102
+ ``` java
103
+ @WithWiremock (... )
104
+ @SpringBootTest
105
+ public class WiremockTest {
106
+
107
+ @Autowired
108
+ private WireMockServer wiremock;
109
+ }
110
+ ```
111
+
112
+ You can then use the normal WireMock API in your test methods to define stubs and verifications.
113
+
114
+ ### Annotation based stubbing
115
+ If you opt-in to use annotation based stubbing provided by this library you gain the advantages of full declarative
116
+ stubbing and easily reusable stubs.
117
+
118
+ > ** Warning** : Please note that using annotation based stubbing will make it harder to get rid of this library from your
119
+ > code base in the future. You should consider to only use WireMock based stubbing to reduce coupling to this library.
120
+
121
+ Not all WireMock features (e.g. verifications) are available in annotation based stubbing. It is always possible though
122
+ to combine annotation based stubs with plain WireMock based stubs as describe above.
123
+
124
+ #### Simple stubs
125
+ You can define a simple stub by annotating your test/test class with ` @HttpStub ` . If you specify no further attributes,
126
+ the mock will now respond with ` 200 OK ` for every request it receives. Note that all additional attributes are optional.
127
+
128
+ Here is a more sophisticated stub example:
129
+ ``` java
130
+ @HttpStub (
131
+ onRequest = @Request (
132
+ withMethod = " POST" ,
133
+ toUrlPath = " /endpoint" ,
134
+ withQueryParameters = " param=matching:[a-z]+" ,
135
+ containingHeaders = " Request-Header=eq:value" ,
136
+ containingCookies = " sessionId=containing:123456" ,
137
+ withBody = " containing:Just a body" ,
138
+ authenticatedBy = @Auth (
139
+ basicAuthUsername = " username" ,
140
+ basicAuthPassword = " password" )),
141
+ respond = @Response (
142
+ withStatus = HttpStatus . CREATED ,
143
+ withBody = " Hello World" ,
144
+ withContentType = " application/text" ,
145
+ withHeaders = " Response-Header=value" ))
146
+ ```
147
+
148
+ #### String matching
149
+ All stub request attributes that expect a String value optionally take a matcher prefix like shown in the above example.
150
+ The following prefixes are supported:
151
+ | Prefix | Operation |
152
+ | --------------------| -----------|
153
+ | ` eq: ` | Comparison using ` String.equals ` |
154
+ | ` eqIgnoreCase: ` | Comparison using ` String.equalsIgnoreCase ` |
155
+ | ` eqToJson: ` | Interpretes the strings as json |
156
+ | ` eqToXml ` | Interpretes the strings as xml |
157
+ | ` matching: ` | Comparison using the provided regex pattern |
158
+ | ` notMatching: ` | Comparison using the provided regex pattern but negates the result |
159
+ | ` matchingJsonPath: ` | Interpretes the string as json and matches it against the provided json path |
160
+ | ` matchingXPath: ` | Interpretes the string as xml and matches it against the provided xpath |
161
+ | ` containing: ` | Comparison using ` String.contains ` |
162
+
163
+ No prefix always results in a comparison using ` String.equals ` .
164
+
165
+ #### Multiple responses
166
+ It is possible to define multiple responses that will be returned by the stub when a stub is matched by consecutive
167
+ requests. Internally this feature will create a WireMock scenario, thus you can not combine multiple responses and
168
+ explicit scenario creation using ` Requst.scenario ` .
169
+
170
+ ``` java
171
+ @HttpStub (
172
+ respond = {
173
+ @Response (withStatus = HttpStatus . CREATED ),
174
+ @Response (withStatus = HttpStatus . OK ),
175
+ @Response (withStatus = HttpStatus . ACCEPTED )
176
+ })
177
+ ```
178
+ When stubbing multiple responses you can define what happens when the last response has been returned using
179
+ ` HttpStub.onLastResponse ` with the following options:
180
+
181
+ | ` onLastResponse ` | Behavior |
182
+ | --------------------------| ----------|
183
+ | ` WrapAround.RETURN_ERROR ` | Default behavior. Mock will answer with a ` 403 ` code after the last response |
184
+ | ` WrapAround.START_OVER ` | After the last response the mock will start over and answer with the first response |
185
+ | ` WrapAround.REPEAT ` | The mock keeps returning the last response |
186
+
187
+ ``` java
188
+ @HttpStub (
189
+ // ...
190
+ respond = {
191
+ // ...
192
+ },
193
+ onLastResponse = WrapAround . REPEAT ;
194
+ )
195
+ ```
196
+
197
+ #### Sharing stubs
198
+ It is possible to share stubs among multiple tests. You can either define your stubs on a super class or an interface
199
+ implemented by your test class. However, the preferred way of sharing stubs is to create a new annotation which
200
+ is meta-annotated with all the stubs (and optionally also with ` @WithWiremock ` ) like in the following example:
201
+
202
+ ``` java
203
+ @Retention (RUNTIME )
204
+ @Target (TYPE )
205
+ @WithWiremock (injectHttpHostInto = " sample-service.url" )
206
+ @HttpStub (onRequest = @Request (toUrl = " /info" ),
207
+ respond = @Response (withStatus = HttpStatus . OK , withStatusMessage = " Everything is Ok" ))
208
+ @HttpStub (onRequest = @Request (toUrl = " /submit/entity" , withMethod = " PUT" ), respond = {
209
+ @Response (withStatus = HttpStatus . CREATED , withStatusMessage = " Entity created" ),
210
+ @Response (withStatus = HttpStatus . OK , withStatusMessage = " Entity already exists" )
211
+ })
212
+ public @interface WithSampleServiceMock {
213
+
214
+ }
215
+ ```
216
+
217
+ You can now easily reuse the complete mock definition in any ` SpringBootTest ` :
218
+ ``` java
219
+ @SpringBootTest
220
+ @WithSampleServiceMock
221
+ public class MetaAnnotatedTest {
222
+
223
+ @Value (" ${sample-service.url}" )
224
+ private String sampleServiceUrl;
225
+
226
+ // ...
227
+ }
228
+ ```
229
+
90
230
## Changelog
91
231
232
+
233
+ ### Version 0.0.13
234
+ * Improve documentation
235
+ * [ Change] Move stubbing annotations into their own package: ` de.skuzzle.wiremock.test.stubs ` (** breaking** )
236
+ * [ Change] Deprecated ` HttpStub.wrapAround ` and introduced ` HttpStub.onLastResponse ` with new enum ` WrapAround `
237
+ * [ Add] New properties that will always be injected: ` wiremock.server.http(s)Host ` , ` wiremock.server.http(s)Port `
238
+ * [ Add] ` WrapAround.REPEAT ` which will repeat the last response on every subsequent request
239
+ * [ Add] Allow to globally define required authentication via ` WithWiremock.withGlobalAuthentication `
240
+
241
+ <details >
242
+ <summary ><b >Previous releases</b ></summary >
243
+
244
+ ### Version 0.0.12
245
+ * Just some improvements to the build/release process
246
+
92
247
### Version 0.0.11
93
248
* Just some improvements to the build/release process
94
249
95
250
### Version 0.0.10
96
- * [ FiX ] Readme
97
- * [ Change] Use latest WireMock version
251
+ * [ Fix ] Readme
252
+ * [ Change] Use latest WireMock version ( ` 2.27.1 ` )
98
253
99
254
### Version 0.0.9
100
255
* [ Add] Possibility to set a stub's priority
@@ -136,3 +291,5 @@ can be injected into the Spring application properties, simply replacing an exis
136
291
137
292
### Version 0.0.1
138
293
* Initial prototype
294
+
295
+ </details >
0 commit comments