responseInterceptors = new ArrayList<>();
39 |
40 | /**
41 | * Creates mock of Apache HttpClient
42 | */
43 | public HttpClientMock() {
44 | this("");
45 | }
46 |
47 | /**
48 | * Creates mock of Apache HttpClient with default host. All defined conditions without host will use default host
49 | *
50 | * @param defaultHost default host for later conditions
51 | */
52 | public HttpClientMock(String defaultHost) {
53 | this(defaultHost, new Debugger());
54 | }
55 |
56 | /**
57 | * Creates mock of Apache HttpClient with default host. All defined conditions without host will use default host
58 | *
59 | * @param defaultHost default host for later conditions
60 | * @param debugger debugger used for testing
61 | */
62 | HttpClientMock(String defaultHost, Debugger debugger) {
63 | this.defaultHost = defaultHost;
64 | this.debugger = debugger;
65 | }
66 |
67 | /**
68 | * Resets mock to initial state where there are no rules and no previous requests.
69 | */
70 | public void reset() {
71 | this.rulesUnderConstruction.clear();
72 | this.rules.clear();
73 | this.requests.clear();
74 | }
75 |
76 | /**
77 | * Creates verification builder.
78 | *
79 | * @return request number verification builder
80 | */
81 | public HttpClientVerify verify() {
82 | return new HttpClientVerify(defaultHost, requests);
83 | }
84 |
85 | /**
86 | * Starts defining new rule which requires HTTP POST method.
87 | *
88 | * @return HttpClientMockBuilder which allows to define new rule
89 | */
90 | public HttpClientMockBuilder onPost() {
91 | return newRule(HttpPost.METHOD_NAME);
92 | }
93 |
94 | /**
95 | * Starts defining new rule which requires HTTP GET method.
96 | *
97 | * @return HttpClientMockBuilder which allows to define new rule
98 | */
99 | public HttpClientMockBuilder onGet() {
100 | return newRule(HttpGet.METHOD_NAME);
101 | }
102 |
103 | /**
104 | * Starts defining new rule which requires HTTP DELETE method.
105 | *
106 | * @return HttpClientMockBuilder which allows to define new rule
107 | */
108 | public HttpClientMockBuilder onDelete() {
109 | return newRule(HttpDelete.METHOD_NAME);
110 | }
111 |
112 | /**
113 | * Starts defining new rule which requires HTTP HEAD method.
114 | *
115 | * @return HttpClientMockBuilder which allows to define new rule
116 | */
117 | public HttpClientMockBuilder onHead() {
118 | return newRule(HttpHead.METHOD_NAME);
119 | }
120 |
121 | /**
122 | * Starts defining new rule which requires HTTP OPTIONS method.
123 | *
124 | * @return HttpClientMockBuilder which allows to define new rule
125 | * @deprecated Method name contains misspelling, use {@link #onOptions}
126 | */
127 | @Deprecated
128 | public HttpClientMockBuilder onOption() {
129 | return onOptions();
130 | }
131 |
132 | /**
133 | * Starts defining new rule which requires HTTP OPTIONS method.
134 | *
135 | * @return HttpClientMockBuilder which allows to define new rule
136 | */
137 | public HttpClientMockBuilder onOptions() {
138 | return newRule(HttpOptions.METHOD_NAME);
139 | }
140 |
141 | /**
142 | * Starts defining new rule which requires HTTP PUT method.
143 | *
144 | * @return HttpClientMockBuilder which allows to define new rule
145 | */
146 | public HttpClientMockBuilder onPut() {
147 | return newRule(HttpPut.METHOD_NAME);
148 | }
149 |
150 | /**
151 | * Starts defining new rule which requires HTTP PATCH method.
152 | *
153 | * @return HttpClientMockBuilder which allows to define new rule
154 | */
155 | public HttpClientMockBuilder onPatch() {
156 | return newRule(HttpPatch.METHOD_NAME);
157 | }
158 |
159 | /**
160 | * Starts defining new rule which requires HTTP GET method and url. If provided url starts with "/" request url must be equal to concatenation of default host
161 | * and url. Otherwise request url must equal to provided url. If provided url contains query parameters and/or reference they are parsed and added as a
162 | * separate conditions. For example:
httpClientMock.onGet("http://localhost/login?user=Ben#edit");
is equal to
163 | * httpClientMock.onGet("http://localhost/login").withParameter("user","Ben").withReference("edit);
164 | *
165 | * @param url required url
166 | * @return HttpClientMockBuilder which allows to define new rule
167 | */
168 | public HttpClientMockBuilder onGet(String url) {
169 | return newRule(HttpGet.METHOD_NAME, url);
170 | }
171 |
172 | /**
173 | * Starts defining new rule which requires HTTP POST method and url. URL works the same way as in {@link #onGet(String) onGet}
174 | *
175 | * @param url required url
176 | * @return HttpClientMockBuilder which allows to define new rule
177 | */
178 | public HttpClientMockBuilder onPost(String url) {
179 | return newRule(HttpPost.METHOD_NAME, url);
180 | }
181 |
182 | /**
183 | * Starts defining new rule which requires HTTP PUT method and url. URL works the same way as in {@link #onGet(String) onGet}
184 | *
185 | * @param url required url
186 | * @return HttpClientMockBuilder which allows to define new rule
187 | */
188 | public HttpClientMockBuilder onPut(String url) {
189 | return newRule(HttpPut.METHOD_NAME, url);
190 | }
191 |
192 | /**
193 | * Starts defining new rule which requires HTTP DELETE method and url. URL works the same way as in {@link #onGet(String) onGet}
194 | *
195 | * @param url required url
196 | * @return HttpClientMockBuilder which allows to define new rule
197 | */
198 | public HttpClientMockBuilder onDelete(String url) {
199 | return newRule(HttpDelete.METHOD_NAME, url);
200 | }
201 |
202 | /**
203 | * Starts defining new rule which requires HTTP HEAD method and url. URL works the same way as in {@link #onGet(String) onGet}
204 | *
205 | * @param url required url
206 | * @return HttpClientMockBuilder which allows to define new rule
207 | */
208 | public HttpClientMockBuilder onHead(String url) {
209 | return newRule(HttpHead.METHOD_NAME, url);
210 | }
211 |
212 | /**
213 | * Starts defining new rule which requires HTTP OPTIONS method and url. URL works the same way as in {@link #onGet(String) onGet}
214 | *
215 | * @param url required url
216 | * @return HttpClientMockBuilder which allows to define new rule
217 | */
218 | public HttpClientMockBuilder onOptions(String url) {
219 | return newRule(HttpOptions.METHOD_NAME, url);
220 | }
221 |
222 | /**
223 | * Starts defining new rule which requires HTTP PATCH method and url. URL works the same way as in {@link #onGet(String) onGet}
224 | *
225 | * @param url required url
226 | * @return HttpClientMockBuilder which allows to define new rule
227 | */
228 | public HttpClientMockBuilder onPatch(String url) {
229 | return newRule(HttpPatch.METHOD_NAME, url);
230 | }
231 |
232 | private HttpClientMockBuilder newRule(String method) {
233 | RuleBuilder r = new RuleBuilder(method);
234 | rulesUnderConstruction.add(r);
235 | return new HttpClientMockBuilder(r);
236 | }
237 |
238 | private HttpClientMockBuilder newRule(String method, String url) {
239 | RuleBuilder r = new RuleBuilder(method, defaultHost, url);
240 | rulesUnderConstruction.add(r);
241 | return new HttpClientMockBuilder(r);
242 | }
243 |
244 | @Override
245 | protected CloseableHttpResponse doExecute(HttpHost httpHost, HttpRequest httpRequest, HttpContext httpContext) throws IOException {
246 | finishBuildingRules();
247 | executeRequestInterceptors(httpRequest, httpContext);
248 | HttpResponse response = getHttpResponse(httpHost, httpRequest, httpContext);
249 | executeResponseInterceptors(httpContext, response);
250 | return new HttpResponseProxy(response);
251 | }
252 |
253 | private void executeResponseInterceptors(HttpContext httpContext, HttpResponse response) throws IOException {
254 | try {
255 | for (HttpResponseInterceptor responseInterceptor : responseInterceptors) {
256 | responseInterceptor.process(response, httpContext);
257 | }
258 | } catch (HttpException e) {
259 | throw new IOException(e);
260 | }
261 | }
262 |
263 | private HttpResponse getHttpResponse(HttpHost httpHost, HttpRequest httpRequest, HttpContext httpContext) throws IOException {
264 | Request request = new Request(httpHost, httpRequest, httpContext);
265 | requests.add(request);
266 | Rule rule = rules.stream()
267 | .filter(r -> r.matches(httpHost, httpRequest, httpContext))
268 | .reduce((a, b) -> b)
269 | .orElse(Rule.NOT_FOUND);
270 | if (isDebuggingTurnOn || rule == Rule.NOT_FOUND) {
271 | debugger.debug(rules, request);
272 | }
273 | return rule.nextResponse(request);
274 | }
275 |
276 | private void executeRequestInterceptors(HttpRequest httpRequest, HttpContext httpContext) throws IOException {
277 | try {
278 | for (HttpRequestInterceptor requestInterceptor : requestInterceptors) {
279 | requestInterceptor.process(httpRequest, httpContext);
280 | }
281 | } catch (HttpException e) {
282 | throw new IOException(e);
283 | }
284 | }
285 |
286 | private void finishBuildingRules() {
287 | synchronized (rulesUnderConstruction) {
288 | for (RuleBuilder ruleBuilder : rulesUnderConstruction) {
289 | rules.add(ruleBuilder.toRule());
290 | }
291 | rulesUnderConstruction.clear();
292 | }
293 | }
294 |
295 | @Override
296 | public void close() throws IOException {
297 | }
298 |
299 | @Override
300 | public HttpParams getParams() {
301 | return params;
302 | }
303 |
304 | @Override
305 | public ClientConnectionManager getConnectionManager() {
306 | return null;
307 | }
308 |
309 | public void debugOn() {
310 | isDebuggingTurnOn = true;
311 | }
312 |
313 | public void debugOff() {
314 | isDebuggingTurnOn = false;
315 | }
316 |
317 | public void addRequestInterceptor(HttpRequestInterceptor requestInterceptor) {
318 | this.requestInterceptors.add(requestInterceptor);
319 | }
320 |
321 | public void addResponseInterceptor(HttpResponseInterceptor responseInterceptor) {
322 | this.responseInterceptors.add(responseInterceptor);
323 | }
324 | }
325 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/HttpClientMockBuilder.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static org.hamcrest.Matchers.equalTo;
4 |
5 | import com.github.paweladamski.httpclientmock.action.Action;
6 | import com.github.paweladamski.httpclientmock.condition.BodyMatcher;
7 | import com.github.paweladamski.httpclientmock.condition.Condition;
8 | import com.github.paweladamski.httpclientmock.condition.HeaderCondition;
9 | import com.github.paweladamski.httpclientmock.matchers.ParametersMatcher;
10 | import java.io.IOException;
11 | import java.nio.charset.Charset;
12 | import java.nio.charset.StandardCharsets;
13 | import java.util.Collection;
14 | import org.apache.http.NameValuePair;
15 | import org.apache.http.entity.ContentType;
16 | import org.hamcrest.Matcher;
17 |
18 | public class HttpClientMockBuilder {
19 |
20 | private final RuleBuilder ruleBuilder;
21 | private final HttpClientResponseBuilder responseBuilder;
22 |
23 | HttpClientMockBuilder(RuleBuilder rule) {
24 | this.ruleBuilder = rule;
25 | this.responseBuilder = new HttpClientResponseBuilder(rule);
26 | }
27 |
28 | /**
29 | * Adds header condition. Header must be equal to provided value.
30 | *
31 | * @param header header name
32 | * @param value expected value
33 | * @return condition builder
34 | */
35 | public HttpClientMockBuilder withHeader(String header, String value) {
36 | return withHeader(header, equalTo(value));
37 | }
38 |
39 | /**
40 | * Adds header condition. Header must be equal to provided value.
41 | *
42 | * @param header header name
43 | * @param matcher header value matcher
44 | * @return condition builder
45 | */
46 | public HttpClientMockBuilder withHeader(String header, Matcher matcher) {
47 | ruleBuilder.addCondition(new HeaderCondition(header, matcher));
48 | return this;
49 | }
50 |
51 | /**
52 | * Adds reference condition. Reference must be equal to provided value.
53 | *
54 | * @param reference expected reference
55 | * @return conditions builder
56 | */
57 | public HttpClientMockBuilder withReference(String reference) {
58 | return withReference(equalTo(reference));
59 | }
60 |
61 | /**
62 | * Adds reference condition. Reference must match.
63 | *
64 | * @param matcher reference matcher
65 | * @return conditions builder
66 | */
67 | public HttpClientMockBuilder withReference(Matcher matcher) {
68 | ruleBuilder.addReferenceCondition(matcher);
69 | return this;
70 | }
71 |
72 | /**
73 | * Adds parameter condition. Parameter must be equal to provided value.
74 | *
75 | * @param name parameter name
76 | * @param value expected parameter value
77 | * @return condition builder
78 | */
79 | public HttpClientMockBuilder withParameter(String name, String value) {
80 | return withParameter(name, equalTo(value));
81 | }
82 |
83 | /**
84 | * Adds parameter condition. Parameter value must match.
85 | *
86 | * @param name parameter name
87 | * @param matcher parameter value matcher
88 | * @return condition builder
89 | */
90 | public HttpClientMockBuilder withParameter(String name, Matcher matcher) {
91 | ruleBuilder.addParameterCondition(name, matcher);
92 | return this;
93 | }
94 |
95 | /**
96 | * Request body must contain the given URL-encoded form parameter (typically found in POST requests). Alternatively, parameters may be specified all at once
97 | * using {@link #withFormParameters(ParametersMatcher)}.
98 | *
99 | * @param name parameter name
100 | * @param value expected parameter value
101 | * @return condition builder
102 | */
103 | public HttpClientMockBuilder withFormParameter(String name, String value) {
104 | return withFormParameter(name, equalTo(value));
105 | }
106 |
107 | /**
108 | * Request body must contain the given URL-encoded form parameter (typically found in POST requests). Alternatively, parameters may be specified all at once
109 | * using {@link #withFormParameters(ParametersMatcher)}.
110 | *
111 | * @param name parameter name
112 | * @param matcher parameter value matcher
113 | * @return condition builder
114 | */
115 | public HttpClientMockBuilder withFormParameter(String name, Matcher matcher) {
116 | ruleBuilder.addFormParameterCondition(name, matcher);
117 | return this;
118 | }
119 |
120 | /**
121 | * Request body must contain the given URL-encoded form parameters (typically used in POST requests). Alternatively, parameters may be specified individually
122 | * using {@link #withFormParameter(String, Matcher)}.
123 | *
124 | * @param parameters the parameters
125 | * @return condition builder
126 | */
127 | public HttpClientMockBuilder withFormParameters(ParametersMatcher parameters) {
128 | ruleBuilder.addFormParameterConditions(parameters);
129 | return this;
130 | }
131 |
132 | /**
133 | * Adds custom conditions.
134 | *
135 | * @param condition custom condition
136 | * @return condition builder
137 | */
138 | public HttpClientMockBuilder with(Condition condition) {
139 | ruleBuilder.addCondition(condition);
140 | return this;
141 | }
142 |
143 | /**
144 | * Adds body condition. Request body must match provided matcher.
145 | *
146 | * @param matcher custom condition
147 | * @return condition builder
148 | */
149 | public HttpClientMockBuilder withBody(Matcher matcher) {
150 | ruleBuilder.addCondition(new BodyMatcher(matcher));
151 | return this;
152 | }
153 |
154 | /**
155 | * Adds host condition. Request host must be equal to provided value.
156 | *
157 | * @param host expected host
158 | * @return condition builder
159 | */
160 | public HttpClientMockBuilder withHost(String host) {
161 | ruleBuilder.addHostCondition(host);
162 | return this;
163 | }
164 |
165 | /**
166 | * Adds path condition. Request path must be equal to provided value.
167 | *
168 | * @param path expected path
169 | * @return condition builder
170 | */
171 | public HttpClientMockBuilder withPath(String path) {
172 | return withPath(equalTo(path));
173 | }
174 |
175 | /**
176 | * Adds path condition. Request path must match.
177 | *
178 | * @param matcher path matcher
179 | * @return condition builder
180 | */
181 | public HttpClientMockBuilder withPath(Matcher matcher) {
182 | ruleBuilder.addPathCondition(matcher);
183 | return this;
184 | }
185 |
186 | /**
187 | * Allows extra parameters (not defined in condition) in query.
188 | *
189 | * @return condition builder
190 | */
191 | public HttpClientMockBuilder withExtraParameters() {
192 | ruleBuilder.setAllowExtraParameters(true);
193 | return this;
194 | }
195 |
196 | /**
197 | * Disallows extra parameters (not defined in condition) in query.
198 | *
199 | * @return condition builder
200 | */
201 | public HttpClientMockBuilder withoutExtraParameters() {
202 | ruleBuilder.setAllowExtraParameters(false);
203 | return this;
204 | }
205 |
206 | /**
207 | * Allows extra parameters (not defined in condition) in form.
208 | *
209 | * @return condition builder
210 | */
211 | public HttpClientMockBuilder withExtraFormParameters() {
212 | ruleBuilder.setAllowExtraFormParameters(true);
213 | return this;
214 | }
215 |
216 | /**
217 | * Disallows extra parameters (not defined in condition) in form.
218 | *
219 | * @return condition builder
220 | */
221 | public HttpClientMockBuilder withoutExtraFormParameters() {
222 | ruleBuilder.setAllowExtraFormParameters(false);
223 | return this;
224 | }
225 |
226 | /**
227 | * Adds custom action.
228 | *
229 | * @param action custom action
230 | * @return response builder
231 | */
232 | public HttpClientResponseBuilder doAction(Action action) {
233 | return responseBuilder.doAction(action);
234 | }
235 |
236 | /**
237 | * Adds action which returns provided response in UTF-8 and status 200.
238 | *
239 | * @param response response to return
240 | * @return response builder
241 | */
242 | public HttpClientResponseBuilder doReturn(String response) {
243 | return responseBuilder.doReturn(response);
244 | }
245 |
246 | /**
247 | * Adds action which returns provided response and status in UTF-8.
248 | *
249 | * @param statusCode status to return
250 | * @param response response to return
251 | * @return response builder
252 | */
253 | public HttpClientResponseBuilder doReturn(int statusCode, String response) {
254 | return responseBuilder.doReturn(statusCode, response);
255 | }
256 |
257 | /**
258 | * Adds action which returns provided response in provided charset and status 200.
259 | *
260 | * @param response response to return
261 | * @param charset charset to return
262 | * @return response builder
263 | */
264 | public HttpClientResponseBuilder doReturn(String response, Charset charset) {
265 | return responseBuilder.doReturn(response, charset);
266 | }
267 |
268 | /**
269 | * Adds action which returns provided response in provided charset and status.
270 | *
271 | * @param statusCode status to return
272 | * @param response response to return
273 | * @param charset the charset
274 | * @return response builder
275 | */
276 | public HttpClientResponseBuilder doReturn(int statusCode, String response, Charset charset) {
277 | return responseBuilder.doReturn(statusCode, response, charset);
278 | }
279 |
280 | /**
281 | * Adds action which returns provided response in provided charset, content-type and status 200.
282 | *
283 | * @param response response to return
284 | * @return response builder
285 | */
286 | public HttpClientResponseBuilder doReturn(String response, Charset charset, ContentType contentType) {
287 | return responseBuilder.doReturn(response, charset, contentType);
288 | }
289 |
290 | /**
291 | * Adds action which returns provided status and null entity.
292 | *
293 | * @param statusCode status to return
294 | * @return response builder
295 | */
296 | public HttpClientResponseBuilder doReturnWithStatus(int statusCode) {
297 | return responseBuilder.doReturnWithStatus(statusCode);
298 | }
299 |
300 | /**
301 | * Adds action which returns provided status with reason and null entity.
302 | *
303 | * @param statusCode status to return
304 | * @param reason reason to return
305 | * @return response builder
306 | */
307 | public HttpClientResponseBuilder doReturnWithStatus(int statusCode, String reason) {
308 | return responseBuilder.doReturnWithStatus(statusCode, reason);
309 | }
310 |
311 | /**
312 | * Adds action which returns empty message and provided status.
313 | *
314 | * @param statusCode status to return
315 | * @return response builder
316 | * @deprecated use doReturnWithStatus instead
317 | */
318 | @Deprecated
319 | public HttpClientResponseBuilder doReturnStatus(int statusCode) {
320 | return responseBuilder.doReturnStatus(statusCode);
321 | }
322 |
323 | /**
324 | * Adds action which throws provided exception.
325 | *
326 | * @param exception exception to be thrown
327 | * @return response builder
328 | */
329 | public HttpClientResponseBuilder doThrowException(IOException exception) {
330 | return responseBuilder.doThrowException(exception);
331 | }
332 |
333 | /**
334 | * Adds action which returns provided JSON in UTF-8 and status 200. Additionally it sets "Content-type" header to "application/json".
335 | *
336 | * @param response JSON to return
337 | * @return response builder
338 | */
339 | public HttpClientResponseBuilder doReturnJSON(String response) {
340 | return responseBuilder.doReturnJSON(response);
341 | }
342 |
343 | /**
344 | * Adds action which returns provided JSON in provided charset and status 200. Additionally it sets "Content-type" header to "application/json".
345 | *
346 | * @param response JSON to return
347 | * @return response builder
348 | */
349 | public HttpClientResponseBuilder doReturnJSON(String response, Charset charset) {
350 | return responseBuilder.doReturnJSON(response, charset);
351 | }
352 |
353 | /**
354 | * Adds action which returns provided XML in UTF-8 and status 200. Additionally it sets "Content-type" header to "application/xml".
355 | *
356 | * @param response JSON to return
357 | * @return response builder
358 | */
359 | public HttpClientResponseBuilder doReturnXML(String response) {
360 | return responseBuilder.doReturnXML(response);
361 | }
362 |
363 | /**
364 | * Adds action which returns provided XML in provided charset and status 200. Additionally it sets "Content-type" header to "application/xml".
365 | *
366 | * @param response JSON to return
367 | * @return response builder
368 | */
369 | public HttpClientResponseBuilder doReturnXML(String response, Charset charset) {
370 | return responseBuilder.doReturnXML(response, charset);
371 | }
372 |
373 | /**
374 | * Adds action which returns provided URL-encoded parameter response in UTF-8 and status 200. Additionally it sets "Content-type" header to
375 | * "application/x-www-form-urlencoded".
376 | *
377 | * @param parameters parameters to return
378 | * @return response builder
379 | */
380 | public HttpClientResponseBuilder doReturnFormParams(Collection parameters) {
381 | return doReturnFormParams(parameters, StandardCharsets.UTF_8);
382 | }
383 |
384 | /**
385 | * Adds action which returns provided URL-encoded parameter response in provided charset and status 200. Additionally it sets "Content-type" header to
386 | * "application/x-www-form-urlencoded".
387 | *
388 | * @param parameters parameters to return
389 | * @return response builder
390 | */
391 | public HttpClientResponseBuilder doReturnFormParams(Collection parameters, Charset charset) {
392 | return responseBuilder.doReturnFormParams(parameters, charset);
393 | }
394 |
395 | }
396 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/HttpClientResponseBuilder.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static org.apache.http.entity.ContentType.APPLICATION_JSON;
4 | import static org.apache.http.entity.ContentType.APPLICATION_XML;
5 |
6 | import com.github.paweladamski.httpclientmock.action.Action;
7 | import com.github.paweladamski.httpclientmock.action.CookieAction;
8 | import com.github.paweladamski.httpclientmock.action.ExceptionAction;
9 | import com.github.paweladamski.httpclientmock.action.HeaderAction;
10 | import com.github.paweladamski.httpclientmock.action.StatusWithEmptyEntityResponse;
11 | import com.github.paweladamski.httpclientmock.action.StatusWithNullEntityResponse;
12 | import com.github.paweladamski.httpclientmock.action.StringResponse;
13 | import com.github.paweladamski.httpclientmock.action.UrlEncodedFormEntityResponse;
14 | import java.io.IOException;
15 | import java.nio.charset.Charset;
16 | import java.nio.charset.StandardCharsets;
17 | import java.util.Collection;
18 | import org.apache.http.NameValuePair;
19 | import org.apache.http.entity.ContentType;
20 |
21 | public class HttpClientResponseBuilder {
22 |
23 | private final RuleBuilder newRule;
24 |
25 | HttpClientResponseBuilder(RuleBuilder rule) {
26 | this.newRule = rule;
27 | }
28 |
29 | /**
30 | * Sets response header.
31 | *
32 | * @param name header name
33 | * @param value header value
34 | * @return response builder
35 | */
36 | public HttpClientResponseBuilder withHeader(String name, String value) {
37 | Action lastAction = newRule.getLastAction();
38 | HeaderAction headerAction = new HeaderAction(lastAction, name, value);
39 | newRule.overrideLastAction(headerAction);
40 | return this;
41 | }
42 |
43 | /**
44 | * Sets response status code.
45 | *
46 | * @param statusCode response status code
47 | * @return response builder
48 | */
49 | public HttpClientResponseBuilder withStatus(int statusCode) {
50 | Action lastAction = newRule.getLastAction();
51 | StatusWithEmptyEntityResponse statusAction = new StatusWithEmptyEntityResponse(lastAction, statusCode);
52 | newRule.overrideLastAction(statusAction);
53 | return this;
54 | }
55 |
56 | /**
57 | * Sets response status code and status reason.
58 | *
59 | * @param statusCode response status code
60 | * @param statusReason response status reason
61 | * @return response builder
62 | */
63 | public HttpClientResponseBuilder withStatus(int statusCode, String statusReason) {
64 | Action lastAction = newRule.getLastAction();
65 | StatusWithEmptyEntityResponse statusAction = new StatusWithEmptyEntityResponse(lastAction, statusCode, statusReason);
66 | newRule.overrideLastAction(statusAction);
67 | return this;
68 | }
69 |
70 | /**
71 | * Sets response cookie
72 | *
73 | * @param cookieName cookie name
74 | * @param cookieValue cookie value
75 | * @return response builder
76 | */
77 | public HttpClientResponseBuilder withCookie(String cookieName, String cookieValue) {
78 | Action lastAction = newRule.getLastAction();
79 | CookieAction cookieAction = new CookieAction(lastAction, cookieName, cookieValue);
80 | newRule.overrideLastAction(cookieAction);
81 | return this;
82 | }
83 |
84 | /**
85 | * Adds custom action.
86 | *
87 | * @param action custom action
88 | * @return response builder
89 | */
90 | public HttpClientResponseBuilder doAction(Action action) {
91 | newRule.addAction(action);
92 | return new HttpClientResponseBuilder(newRule);
93 | }
94 |
95 | /**
96 | * Adds action which returns provided response in UTF-8 and status 200.
97 | *
98 | * @param response response to return
99 | * @return response builder
100 | */
101 | public HttpClientResponseBuilder doReturn(String response) {
102 | return doReturn(response, StandardCharsets.UTF_8);
103 | }
104 |
105 | /**
106 | * Adds action which returns provided response in UTF-8 with status code.
107 | *
108 | * @param statusCode status to return
109 | * @param response response to return
110 | * @return response builder
111 | */
112 | public HttpClientResponseBuilder doReturn(int statusCode, String response) {
113 | return doReturn(statusCode, response, StandardCharsets.UTF_8);
114 | }
115 |
116 | /**
117 | * Adds action which returns provided response in provided charset and status 200.
118 | *
119 | * @param response response to return
120 | * @return response builder
121 | */
122 | public HttpClientResponseBuilder doReturn(String response, Charset charset) {
123 | newRule.addAction(new StringResponse(response, charset));
124 | return new HttpClientResponseBuilder(newRule);
125 | }
126 |
127 | /**
128 | * Adds action which returns provided response in provided charset, content type and status 200.
129 | *
130 | * @param response response to return
131 | * @return response builder
132 | */
133 | public HttpClientResponseBuilder doReturn(String response, Charset charset, ContentType contentType) {
134 | newRule.addAction(new StringResponse(response, charset, contentType));
135 | return new HttpClientResponseBuilder(newRule);
136 | }
137 |
138 | /**
139 | * Adds action which returns provided response in provided charset and status code.
140 | *
141 | * @param statusCode status to return
142 | * @param response response to return
143 | * @param charset the charset
144 | * @return response builder
145 | */
146 | public HttpClientResponseBuilder doReturn(int statusCode, String response, Charset charset) {
147 | newRule.addAction(new StringResponse(statusCode, response, charset));
148 | return new HttpClientResponseBuilder(newRule);
149 | }
150 |
151 | /**
152 | * Adds action which returns provided status and null entity.
153 | *
154 | * @param statusCode status to return
155 | * @return response builder
156 | */
157 | public HttpClientResponseBuilder doReturnWithStatus(int statusCode) {
158 | newRule.addAction(new StatusWithNullEntityResponse(statusCode));
159 | return new HttpClientResponseBuilder(newRule);
160 | }
161 |
162 | /**
163 | * Adds action which returns provided status with reason and null entity.
164 | *
165 | * @param statusCode status to return
166 | * @param reason reason to return
167 | * @return response builder
168 | */
169 | public HttpClientResponseBuilder doReturnWithStatus(int statusCode, String reason) {
170 | newRule.addAction(new StatusWithNullEntityResponse(statusCode, reason));
171 | return new HttpClientResponseBuilder(newRule);
172 | }
173 |
174 |
175 | /**
176 | * Adds action which returns empty message and provided status.
177 | *
178 | * @param statusCode status to return
179 | * @return response builder
180 | * @deprecated use doReturnWithStatus instead
181 | */
182 | @Deprecated
183 | public HttpClientResponseBuilder doReturnStatus(int statusCode) {
184 | newRule.addAction(new StatusWithEmptyEntityResponse(statusCode));
185 | return new HttpClientResponseBuilder(newRule);
186 | }
187 |
188 | /**
189 | * Adds action which throws provided exception.
190 | *
191 | * @param exception exception to be thrown
192 | * @return response builder
193 | */
194 | public HttpClientResponseBuilder doThrowException(IOException exception) {
195 | newRule.addAction(new ExceptionAction(exception));
196 | return new HttpClientResponseBuilder(newRule);
197 | }
198 |
199 | /**
200 | * Adds action which returns provided JSON in UTF-8 and status 200. Additionally it sets "Content-type" header to "application/json".
201 | *
202 | * @param response JSON to return
203 | * @return response builder
204 | */
205 | public HttpClientResponseBuilder doReturnJSON(String response) {
206 | return doReturnJSON(response, StandardCharsets.UTF_8);
207 | }
208 |
209 | /**
210 | * Adds action which returns provided JSON in provided encoding and status 200. Additionally it sets "Content-type" header to "application/json".
211 | *
212 | * @param response JSON to return
213 | * @return response builder
214 | */
215 | public HttpClientResponseBuilder doReturnJSON(String response, Charset charset) {
216 | return doReturn(response, charset, APPLICATION_JSON);
217 | }
218 |
219 | /**
220 | * Adds action which returns provided XML in UTF-8 and status 200. Additionally it sets "Content-type" header to "application/xml".
221 | *
222 | * @param response JSON to return
223 | * @return response builder
224 | */
225 | public HttpClientResponseBuilder doReturnXML(String response) {
226 | return doReturnXML(response, StandardCharsets.UTF_8);
227 | }
228 |
229 | /**
230 | * Adds action which returns provided XML in UTF-8 and status 200. Additionally it sets "Content-type" header to "application/xml".
231 | *
232 | * @param response JSON to return
233 | * @return response builder
234 | */
235 | public HttpClientResponseBuilder doReturnXML(String response, Charset charset) {
236 | return doReturn(response, charset, APPLICATION_XML);
237 | }
238 |
239 | /**
240 | * Adds action which returns provided name/value pairs as URL-encoded form response in UTF-8 and status 200. Additionally it sets "Content-type" header to
241 | * "application/x-www-form-urlencoded".
242 | *
243 | * @param formParameters the parameters to include in the response
244 | * @return response builder
245 | */
246 | public HttpClientResponseBuilder doReturnFormParams(Collection formParameters) {
247 | return doReturnFormParams(formParameters, StandardCharsets.UTF_8);
248 | }
249 |
250 | /**
251 | * Adds action which returns provided name/value pairs as URL-encoded form response and status 200. Additionally it sets "Content-type" header to
252 | * "application/x-www-form-urlencoded".
253 | *
254 | * @param formParameters the parameters to include in the response
255 | * @return response builder
256 | */
257 | public HttpClientResponseBuilder doReturnFormParams(Collection formParameters, Charset charset) {
258 | newRule.addAction(new UrlEncodedFormEntityResponse(formParameters, charset));
259 | return new HttpClientResponseBuilder(newRule);
260 | }
261 |
262 | }
263 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/HttpClientVerify.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import java.util.List;
4 |
5 | import org.apache.http.client.methods.HttpDelete;
6 | import org.apache.http.client.methods.HttpGet;
7 | import org.apache.http.client.methods.HttpHead;
8 | import org.apache.http.client.methods.HttpOptions;
9 | import org.apache.http.client.methods.HttpPatch;
10 | import org.apache.http.client.methods.HttpPost;
11 | import org.apache.http.client.methods.HttpPut;
12 |
13 | public class HttpClientVerify {
14 |
15 | private final String defaultHost;
16 | private final List requests;
17 |
18 | public HttpClientVerify(String defaultHost, List requests) {
19 | this.requests = requests;
20 | this.defaultHost = defaultHost;
21 | }
22 |
23 | private HttpClientVerifyBuilder newRule(String method) {
24 | RuleBuilder r = new RuleBuilder(method);
25 | return new HttpClientVerifyBuilder(r, requests);
26 | }
27 |
28 | private HttpClientVerifyBuilder newRule(String method, String url) {
29 | RuleBuilder r = new RuleBuilder(method, defaultHost, url);
30 | return new HttpClientVerifyBuilder(r, requests);
31 | }
32 |
33 | public HttpClientVerifyBuilder post(String url) {
34 | return newRule(HttpPost.METHOD_NAME, url);
35 | }
36 |
37 | public HttpClientVerifyBuilder get(String url) {
38 | return newRule(HttpGet.METHOD_NAME, url);
39 | }
40 |
41 | public HttpClientVerifyBuilder put(String url) {
42 | return newRule(HttpPut.METHOD_NAME, url);
43 | }
44 |
45 | public HttpClientVerifyBuilder delete(String url) {
46 | return newRule(HttpDelete.METHOD_NAME, url);
47 | }
48 |
49 | public HttpClientVerifyBuilder head(String url) {
50 | return newRule(HttpHead.METHOD_NAME, url);
51 | }
52 |
53 | public HttpClientVerifyBuilder options(String url) {
54 | return newRule(HttpOptions.METHOD_NAME, url);
55 | }
56 |
57 | public HttpClientVerifyBuilder patch(String url) {
58 | return newRule(HttpPatch.METHOD_NAME, url);
59 | }
60 |
61 | public HttpClientVerifyBuilder post() {
62 | return newRule(HttpPost.METHOD_NAME);
63 | }
64 |
65 | public HttpClientVerifyBuilder get() {
66 | return newRule(HttpGet.METHOD_NAME);
67 | }
68 |
69 | public HttpClientVerifyBuilder put() {
70 | return newRule(HttpPut.METHOD_NAME);
71 | }
72 |
73 | public HttpClientVerifyBuilder delete() {
74 | return newRule(HttpDelete.METHOD_NAME);
75 | }
76 |
77 | public HttpClientVerifyBuilder head() {
78 | return newRule(HttpHead.METHOD_NAME);
79 | }
80 |
81 | public HttpClientVerifyBuilder options() {
82 | return newRule(HttpOptions.METHOD_NAME);
83 | }
84 |
85 | public HttpClientVerifyBuilder patch() {
86 | return newRule(HttpPatch.METHOD_NAME);
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/HttpClientVerifyBuilder.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static org.hamcrest.Matchers.equalTo;
4 |
5 | import com.github.paweladamski.httpclientmock.condition.BodyMatcher;
6 | import com.github.paweladamski.httpclientmock.condition.Condition;
7 | import com.github.paweladamski.httpclientmock.condition.HeaderCondition;
8 | import com.github.paweladamski.httpclientmock.matchers.ParametersMatcher;
9 | import java.util.List;
10 | import org.hamcrest.Matcher;
11 |
12 | public class HttpClientVerifyBuilder {
13 |
14 | private final RuleBuilder ruleBuilder;
15 | private final List requests;
16 |
17 | HttpClientVerifyBuilder(RuleBuilder ruleBuilder, List requests) {
18 | this.requests = requests;
19 | this.ruleBuilder = ruleBuilder;
20 | }
21 |
22 | /**
23 | * Adds header condition. Header must be equal to provided value.
24 | *
25 | * @param header header name
26 | * @param value expected value
27 | * @return verification builder
28 | */
29 | public HttpClientVerifyBuilder withHeader(String header, String value) {
30 | return withHeader(header, equalTo(value));
31 | }
32 |
33 | /**
34 | * Adds header condition. Header must be equal to provided value.
35 | *
36 | * @param header header name
37 | * @param matcher header value matcher
38 | * @return verification builder
39 | */
40 | public HttpClientVerifyBuilder withHeader(String header, Matcher matcher) {
41 | ruleBuilder.addCondition(new HeaderCondition(header, matcher));
42 | return this;
43 | }
44 |
45 | /**
46 | * Adds reference condition. Reference must be equal to provided value.
47 | *
48 | * @param reference expected reference
49 | * @return conditions builder
50 | */
51 | public HttpClientVerifyBuilder withReference(String reference) {
52 | return withReference(equalTo(reference));
53 | }
54 |
55 | /**
56 | * Adds reference condition. Reference must match.
57 | *
58 | * @param matcher reference matcher
59 | * @return conditions builder
60 | */
61 | public HttpClientVerifyBuilder withReference(Matcher matcher) {
62 | ruleBuilder.addReferenceCondition(matcher);
63 | return this;
64 | }
65 |
66 | /**
67 | * Adds parameter condition. Parameter must be equal to provided value.
68 | *
69 | * @param name parameter name
70 | * @param value expected parameter value
71 | * @return verification builder
72 | */
73 | public HttpClientVerifyBuilder withParameter(String name, String value) {
74 | return withParameter(name, equalTo(value));
75 | }
76 |
77 | /**
78 | * Adds parameter condition. Parameter value must match.
79 | *
80 | * @param name parameter name
81 | * @param matcher parameter value matcher
82 | * @return verification builder
83 | */
84 | public HttpClientVerifyBuilder withParameter(String name, Matcher matcher) {
85 | ruleBuilder.addParameterCondition(name, matcher);
86 | return this;
87 | }
88 |
89 | /**
90 | * Request body must contain the given URL-encoded form parameter (typically found in POST requests). Alternatively, parameters may be specified all at once
91 | * using {@link #withFormParameters(ParametersMatcher)}.
92 | *
93 | * @param name parameter name
94 | * @param value expected parameter value
95 | * @return verification builder
96 | */
97 | public HttpClientVerifyBuilder withFormParameter(String name, String value) {
98 | return withFormParameter(name, equalTo(value));
99 | }
100 |
101 | /**
102 | * Request body must contain the given URL-encoded form parameter (typically found in POST requests). Alternatively, parameters may be specified all at once
103 | * using {@link #withFormParameters(ParametersMatcher)}.
104 | *
105 | * @param name parameter name
106 | * @param matcher parameter value matcher
107 | * @return verification builder
108 | */
109 | public HttpClientVerifyBuilder withFormParameter(String name, Matcher matcher) {
110 | ruleBuilder.addFormParameterCondition(name, matcher);
111 | return this;
112 | }
113 |
114 | /**
115 | * Request body must contain the given URL-encoded form parameters (typically used in POST requests). Alternatively, parameters may be specified individually
116 | * using {@link #withFormParameter(String, Matcher)}.
117 | *
118 | * @param parameters the parameters
119 | * @return condition builder
120 | */
121 | public HttpClientVerifyBuilder withFormParameters(ParametersMatcher parameters) {
122 | ruleBuilder.addFormParameterConditions(parameters);
123 | return this;
124 | }
125 |
126 | /**
127 | * Adds custom conditions.
128 | *
129 | * @param condition custom condition
130 | * @return verification builder
131 | */
132 | public HttpClientVerifyBuilder with(Condition condition) {
133 | ruleBuilder.addCondition(condition);
134 | return this;
135 | }
136 |
137 | /**
138 | * Adds body condition. Request body must match provided matcher.
139 | *
140 | * @param matcher custom condition
141 | * @return verification builder
142 | */
143 | public HttpClientVerifyBuilder withBody(Matcher matcher) {
144 | ruleBuilder.addCondition(new BodyMatcher(matcher));
145 | return this;
146 | }
147 |
148 | /**
149 | * Adds host condition. Request host must be equal to provided value.
150 | *
151 | * @param host expected host
152 | * @return verification builder
153 | */
154 | public HttpClientVerifyBuilder withHost(String host) {
155 | ruleBuilder.addHostCondition(host);
156 | return this;
157 | }
158 |
159 | /**
160 | * Adds path condition. Request path must be equal to provided value.
161 | *
162 | * @param path expected path
163 | * @return verification builder
164 | */
165 | public HttpClientVerifyBuilder withPath(String path) {
166 | return withPath(equalTo(path));
167 | }
168 |
169 | /**
170 | * Adds path condition. Request path must match.
171 | *
172 | * @param matcher path matcher
173 | * @return verification builder
174 | */
175 | public HttpClientVerifyBuilder withPath(Matcher matcher) {
176 | ruleBuilder.addPathCondition(matcher);
177 | return this;
178 | }
179 |
180 | /**
181 | * Allows extra parameters (not defined in condition) in query.
182 | *
183 | * @return verification builder
184 | */
185 | public HttpClientVerifyBuilder withExtraParameters() {
186 | ruleBuilder.setAllowExtraParameters(true);
187 | return this;
188 | }
189 |
190 | /**
191 | * Disallows extra parameters (not defined in condition) in query.
192 | *
193 | * @return condition builder
194 | */
195 | public HttpClientVerifyBuilder withoutExtraParameters() {
196 | ruleBuilder.setAllowExtraParameters(false);
197 | return this;
198 | }
199 |
200 | /**
201 | * Allows extra parameters (not defined in condition) in form.
202 | *
203 | * @return verification builder
204 | */
205 | public HttpClientVerifyBuilder withExtraFormParameters() {
206 | ruleBuilder.setAllowExtraFormParameters(true);
207 | return this;
208 | }
209 |
210 | /**
211 | * Disallows extra parameters (not defined in condition) in form.
212 | *
213 | * @return verification builder
214 | */
215 | public HttpClientVerifyBuilder withoutExtraFormParameters() {
216 | ruleBuilder.setAllowExtraFormParameters(false);
217 | return this;
218 | }
219 |
220 | /**
221 | * Verifies if there were no request matching defined conditions.
222 | */
223 | public void notCalled() {
224 | called(0);
225 | }
226 |
227 | /**
228 | * Verifies if there was exactly one request matching defined conditions.
229 | */
230 | public void called() {
231 | called(1);
232 | }
233 |
234 | /**
235 | * Verifies number of request matching defined conditions.
236 | *
237 | * @param numberOfCalls expected number of calls
238 | */
239 | public void called(int numberOfCalls) {
240 | called(equalTo(numberOfCalls));
241 | }
242 |
243 | /**
244 | * Verifies number of request matching defined conditions.
245 | *
246 | * @param numberOfCalls expected number of calls
247 | */
248 | public void called(Matcher numberOfCalls) {
249 | Rule rule = ruleBuilder.toRule();
250 | int matchingCalls = (int) requests.stream()
251 | .filter(rule::matches)
252 | .count();
253 |
254 | if (!numberOfCalls.matches(matchingCalls)) {
255 | throw new IllegalStateException(String.format("Expected %s calls, but found %s.", numberOfCalls, matchingCalls));
256 | }
257 | }
258 |
259 | }
260 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/HttpResponseProxy.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import java.io.IOException;
4 | import java.util.Locale;
5 | import org.apache.http.Header;
6 | import org.apache.http.HeaderIterator;
7 | import org.apache.http.HttpEntity;
8 | import org.apache.http.HttpResponse;
9 | import org.apache.http.ProtocolVersion;
10 | import org.apache.http.StatusLine;
11 | import org.apache.http.client.methods.CloseableHttpResponse;
12 | import org.apache.http.params.HttpParams;
13 |
14 | class HttpResponseProxy implements CloseableHttpResponse {
15 |
16 | private final HttpResponse original;
17 |
18 | public HttpResponseProxy(HttpResponse original) {
19 | this.original = original;
20 |
21 | }
22 |
23 | public void close() throws IOException {
24 |
25 | }
26 |
27 | public StatusLine getStatusLine() {
28 | return this.original.getStatusLine();
29 | }
30 |
31 | public void setStatusLine(StatusLine statusline) {
32 | this.original.setStatusLine(statusline);
33 | }
34 |
35 | public void setStatusLine(ProtocolVersion ver, int code) {
36 | this.original.setStatusLine(ver, code);
37 | }
38 |
39 | public void setStatusLine(ProtocolVersion ver, int code, String reason) {
40 | this.original.setStatusLine(ver, code, reason);
41 | }
42 |
43 | public void setStatusCode(int code) throws IllegalStateException {
44 | this.original.setStatusCode(code);
45 | }
46 |
47 | public void setReasonPhrase(String reason) throws IllegalStateException {
48 | this.original.setReasonPhrase(reason);
49 | }
50 |
51 | public HttpEntity getEntity() {
52 | return this.original.getEntity();
53 | }
54 |
55 | public void setEntity(HttpEntity entity) {
56 | this.original.setEntity(entity);
57 | }
58 |
59 | public Locale getLocale() {
60 | return this.original.getLocale();
61 | }
62 |
63 | public void setLocale(Locale loc) {
64 | this.original.setLocale(loc);
65 | }
66 |
67 | public ProtocolVersion getProtocolVersion() {
68 | return this.original.getProtocolVersion();
69 | }
70 |
71 | public boolean containsHeader(String name) {
72 | return this.original.containsHeader(name);
73 | }
74 |
75 | public Header[] getHeaders(String name) {
76 | return this.original.getHeaders(name);
77 | }
78 |
79 | public Header getFirstHeader(String name) {
80 | return this.original.getFirstHeader(name);
81 | }
82 |
83 | public Header getLastHeader(String name) {
84 | return this.original.getLastHeader(name);
85 | }
86 |
87 | public Header[] getAllHeaders() {
88 | return this.original.getAllHeaders();
89 | }
90 |
91 | public void addHeader(Header header) {
92 | this.original.addHeader(header);
93 | }
94 |
95 | public void addHeader(String name, String value) {
96 | this.original.addHeader(name, value);
97 | }
98 |
99 | public void setHeader(Header header) {
100 | this.original.setHeader(header);
101 | }
102 |
103 | public void setHeader(String name, String value) {
104 | this.original.setHeader(name, value);
105 | }
106 |
107 | public void setHeaders(Header[] headers) {
108 | this.original.setHeaders(headers);
109 | }
110 |
111 | public void removeHeader(Header header) {
112 | this.original.removeHeader(header);
113 | }
114 |
115 | public void removeHeaders(String name) {
116 | this.original.removeHeaders(name);
117 | }
118 |
119 | public HeaderIterator headerIterator() {
120 | return this.original.headerIterator();
121 | }
122 |
123 | public HeaderIterator headerIterator(String name) {
124 | return this.original.headerIterator(name);
125 | }
126 |
127 | /**
128 | * @deprecated
129 | */
130 | @Deprecated
131 | public HttpParams getParams() {
132 | return this.original.getParams();
133 | }
134 |
135 | /**
136 | * @deprecated
137 | */
138 | @Deprecated
139 | public void setParams(HttpParams params) {
140 | this.original.setParams(params);
141 | }
142 |
143 | public String toString() {
144 | return "HttpResponseProxy{" + this.original + '}';
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/Request.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import java.net.URI;
4 | import org.apache.http.HttpHost;
5 | import org.apache.http.HttpRequest;
6 | import org.apache.http.protocol.HttpContext;
7 |
8 | public class Request {
9 |
10 | private final HttpHost httpHost;
11 | private final HttpRequest httpRequest;
12 | private final HttpContext httpContext;
13 |
14 | public Request(HttpHost httpHost, HttpRequest httpRequest, HttpContext httpContext) {
15 |
16 | this.httpHost = httpHost;
17 | this.httpRequest = httpRequest;
18 | this.httpContext = httpContext;
19 | }
20 |
21 | public HttpHost getHttpHost() {
22 | return httpHost;
23 | }
24 |
25 | public HttpRequest getHttpRequest() {
26 | return httpRequest;
27 | }
28 |
29 | public HttpContext getHttpContext() {
30 | return httpContext;
31 | }
32 |
33 | public String getUri() {
34 | URI uri = URI.create(httpRequest.getRequestLine().getUri());
35 | String urlText;
36 | if (uri.isAbsolute()) {
37 | urlText = uri.toString();
38 | } else {
39 | urlText = httpHost.toString() + uri.toString();
40 | }
41 | return urlText;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/Rule.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static java.util.Collections.emptyList;
4 | import static org.apache.http.HttpStatus.SC_NOT_FOUND;
5 |
6 | import com.github.paweladamski.httpclientmock.action.Action;
7 | import com.github.paweladamski.httpclientmock.action.StatusWithEmptyEntityResponse;
8 | import com.github.paweladamski.httpclientmock.condition.Condition;
9 | import java.io.IOException;
10 | import java.util.ArrayList;
11 | import java.util.LinkedList;
12 | import java.util.List;
13 | import org.apache.http.HttpHost;
14 | import org.apache.http.HttpRequest;
15 | import org.apache.http.HttpResponse;
16 | import org.apache.http.protocol.HttpContext;
17 |
18 | public class Rule {
19 |
20 | public static final Rule NOT_FOUND = new Rule(new UrlConditions(), emptyList(), notFoundAction());
21 | private final LinkedList actions;
22 | private final List conditions;
23 | private final UrlConditions urlConditions;
24 |
25 | public Rule(UrlConditions urlConditions, List conditions, List actions) {
26 | this.urlConditions = urlConditions;
27 | this.conditions = conditions;
28 | this.actions = new LinkedList<>(actions);
29 | }
30 |
31 | boolean matches(Request request) {
32 | return urlConditions.matches(request.getUri())
33 | && conditions.stream()
34 | .allMatch(c -> c.matches(request));
35 | }
36 |
37 | boolean matches(HttpHost httpHost, HttpRequest httpRequest, HttpContext httpContext) {
38 | return matches(new Request(httpHost, httpRequest, httpContext));
39 | }
40 |
41 | HttpResponse nextResponse(Request request) throws IOException {
42 | Action action = (actions.size() > 1) ? actions.poll() : actions.peek();
43 | return action.getResponse(request);
44 | }
45 |
46 | public void debug(Request request, Debugger debugger) {
47 | for (Condition condition : conditions) {
48 | condition.debug(request, debugger);
49 | }
50 | urlConditions.debug(request, debugger);
51 | }
52 |
53 | private static List notFoundAction() {
54 | ArrayList actions = new ArrayList<>();
55 | actions.add(new StatusWithEmptyEntityResponse(SC_NOT_FOUND));
56 | return actions;
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/RuleBuilder.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import com.github.paweladamski.httpclientmock.action.Action;
4 | import com.github.paweladamski.httpclientmock.condition.Condition;
5 | import com.github.paweladamski.httpclientmock.condition.HttpMethodCondition;
6 | import com.github.paweladamski.httpclientmock.condition.UrlEncodedFormCondition;
7 | import com.github.paweladamski.httpclientmock.matchers.ParametersMatcher;
8 | import java.util.ArrayList;
9 | import java.util.List;
10 | import org.hamcrest.Matcher;
11 |
12 | class RuleBuilder {
13 |
14 | private final List actions = new ArrayList<>();
15 | private final List conditions = new ArrayList<>();
16 | private final UrlEncodedFormCondition formParametersCondition = new UrlEncodedFormCondition();
17 | private final UrlConditions urlConditions;
18 |
19 | RuleBuilder(String method, String defaultHost, String url) {
20 | this.urlConditions = new UrlParser().parse(buildFinalUrl(defaultHost, url));
21 | addCondition(new HttpMethodCondition(method));
22 | addCondition(formParametersCondition);
23 | setAllowExtraParameters(true);
24 | setAllowExtraFormParameters(true);
25 | }
26 |
27 | RuleBuilder(String method) {
28 | this.urlConditions = new UrlConditions();
29 | addCondition(new HttpMethodCondition(method));
30 | addCondition(formParametersCondition);
31 | setAllowExtraParameters(true);
32 | setAllowExtraFormParameters(true);
33 | }
34 |
35 | private String buildFinalUrl(String defaultHost, String url) {
36 | if (url.startsWith("/")) {
37 | return defaultHost + url;
38 | } else {
39 | return url;
40 | }
41 | }
42 |
43 | void addAction(Action o) {
44 | actions.add(o);
45 | }
46 |
47 | void addCondition(Condition o) {
48 | conditions.add(o);
49 | }
50 |
51 | void addParameterCondition(String name, Matcher matcher) {
52 | urlConditions.getUrlQueryConditions().put(name, matcher);
53 | }
54 |
55 | void addFormParameterCondition(String name, Matcher matcher) {
56 | formParametersCondition.addExpectedParameter(name, matcher);
57 | }
58 |
59 | void addFormParameterConditions(ParametersMatcher parameters) {
60 | formParametersCondition.addExpectedParameters(parameters);
61 | }
62 |
63 | void addReferenceCondition(Matcher matcher) {
64 | urlConditions.setReferenceConditions(matcher);
65 | }
66 |
67 | void addHostCondition(String host) {
68 | UrlParser urlParser = new UrlParser();
69 | urlConditions.setHostConditions(urlParser.parse(host).getHostConditions());
70 | }
71 |
72 | void addPathCondition(Matcher matcher) {
73 | urlConditions.getPathConditions().add(matcher);
74 | }
75 |
76 | Action getLastAction() {
77 | return actions.get(actions.size() - 1);
78 | }
79 |
80 | void overrideLastAction(Action lastAction) {
81 | actions.set(actions.size() - 1, lastAction);
82 | }
83 |
84 | Rule toRule() {
85 | return new Rule(urlConditions, conditions, actions);
86 | }
87 |
88 | public void setAllowExtraParameters(boolean allowExtraParameters) {
89 | urlConditions.getUrlQueryConditions().setAllowExtraParameters(allowExtraParameters);
90 | }
91 |
92 | public void setAllowExtraFormParameters(boolean allowExtraFormParameters) {
93 | formParametersCondition.setAllowExtraParameters(allowExtraFormParameters);
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/UrlConditions.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static org.hamcrest.Matchers.isEmptyOrNullString;
4 |
5 | import com.github.paweladamski.httpclientmock.matchers.MatchersList;
6 | import com.github.paweladamski.httpclientmock.matchers.UrlQueryMatcher;
7 | import java.net.MalformedURLException;
8 | import java.net.URL;
9 | import org.hamcrest.Matcher;
10 | import org.hamcrest.Matchers;
11 | import org.hamcrest.StringDescription;
12 |
13 | public class UrlConditions {
14 |
15 | private static final int EMPTY_PORT = -1;
16 | private UrlQueryMatcher urlQueryConditions = new UrlQueryMatcher();
17 | private Matcher referenceConditions = Matchers.isEmptyOrNullString();
18 | private MatchersList hostConditions = new MatchersList<>();
19 | private MatchersList pathConditions = new MatchersList<>();
20 | private MatchersList portConditions = new MatchersList<>();
21 | private Matcher schemaConditions = Matchers.any(String.class);
22 |
23 | public UrlQueryMatcher getUrlQueryConditions() {
24 | return urlQueryConditions;
25 | }
26 |
27 | public Matcher getReferenceConditions() {
28 | return referenceConditions;
29 | }
30 |
31 | public void setReferenceConditions(Matcher referenceConditions) {
32 | this.referenceConditions = referenceConditions;
33 | }
34 |
35 | public MatchersList getHostConditions() {
36 | return hostConditions;
37 | }
38 |
39 | public void setHostConditions(MatchersList hostConditions) {
40 | this.hostConditions = hostConditions;
41 | }
42 |
43 | public MatchersList getPathConditions() {
44 | return pathConditions;
45 | }
46 |
47 | public MatchersList getPortConditions() {
48 | return portConditions;
49 | }
50 |
51 | public void setSchemaConditions(Matcher schemaConditions) {
52 | this.schemaConditions = schemaConditions;
53 | }
54 |
55 | boolean matches(String urlText) {
56 | try {
57 | URL url = new URL(urlText);
58 |
59 | return hostConditions.allMatches(url.getHost())
60 | && pathConditions.allMatches(url.getPath())
61 | && portConditions.allMatches(url.getPort())
62 | && referenceConditions.matches(url.getRef())
63 | && schemaConditions.matches(url.getProtocol())
64 | && urlQueryConditions.matches(url.getQuery());
65 |
66 | } catch (MalformedURLException e) {
67 | return false;
68 | }
69 | }
70 |
71 |
72 | void debug(Request request, Debugger debugger) {
73 | try {
74 | URL url = new URL(request.getUri());
75 | debugger.message(hostConditions.allMatches(url.getHost()), "schema is " + describe(schemaConditions));
76 | debugger.message(hostConditions.allMatches(url.getHost()), "host is " + hostConditions.describe());
77 | debugger.message(pathConditions.allMatches(url.getPath()), "path is " + pathConditions.describe());
78 | debugger.message(portConditions.allMatches(url.getPort()), "port is " + portDebugDescription());
79 | if (referenceConditions != isEmptyOrNullString() || !referenceConditions.matches(url.getRef())) {
80 | debugger.message(referenceConditions.matches(url.getRef()), "reference is " + describe(referenceConditions));
81 | }
82 | urlQueryConditions.describe(url.getQuery(), debugger);
83 | } catch (MalformedURLException e) {
84 | System.out.println("Can't parse URL: " + request.getUri());
85 | }
86 | }
87 |
88 | private String describe(Matcher matcher) {
89 | return StringDescription.toString(matcher);
90 | }
91 |
92 | private String portDebugDescription() {
93 | return portConditions.allMatches(EMPTY_PORT) ? "empty" : portConditions.describe();
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/UrlParamsParser.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import java.nio.charset.Charset;
4 | import java.nio.charset.StandardCharsets;
5 | import java.util.Collections;
6 | import java.util.List;
7 | import org.apache.http.NameValuePair;
8 | import org.apache.http.client.utils.URLEncodedUtils;
9 |
10 | public class UrlParamsParser {
11 |
12 | public List parse(String query) {
13 | return parse(query, StandardCharsets.UTF_8);
14 | }
15 |
16 | public List parse(String query, Charset charset) {
17 | if (query != null) {
18 | return URLEncodedUtils.parse(query, charset);
19 | } else {
20 | return Collections.emptyList();
21 | }
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/UrlParser.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static org.hamcrest.Matchers.equalTo;
4 | import static org.hamcrest.Matchers.isEmptyOrNullString;
5 |
6 | import java.net.MalformedURLException;
7 | import java.net.URL;
8 | import java.nio.charset.StandardCharsets;
9 | import java.util.List;
10 | import org.apache.http.NameValuePair;
11 | import org.hamcrest.Matchers;
12 |
13 | public class UrlParser {
14 |
15 | public static final int EMPTY_PORT_NUMBER = -1;
16 |
17 | public UrlConditions parse(String urlText) {
18 | try {
19 | UrlConditions conditions = new UrlConditions();
20 | URL url = new URL(urlText);
21 |
22 | String ref = url.getRef();
23 | conditions.setReferenceConditions((ref == null) ? isEmptyOrNullString() : equalTo(ref));
24 |
25 | conditions.setSchemaConditions(Matchers.equalTo(url.getProtocol()));
26 | conditions.getHostConditions().add(equalTo(url.getHost()));
27 | conditions.getPortConditions().add(equalTo(url.getPort()));
28 | conditions.getPathConditions().add(equalTo(url.getPath()));
29 | List params = new UrlParamsParser().parse(url.getQuery(), StandardCharsets.UTF_8);
30 | for (NameValuePair param : params) {
31 | conditions.getUrlQueryConditions().put(param.getName(), equalTo(param.getValue()));
32 | }
33 | return conditions;
34 | } catch (MalformedURLException e) {
35 | throw new IllegalArgumentException(e);
36 | }
37 |
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/action/Action.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.action;
2 |
3 | import com.github.paweladamski.httpclientmock.Request;
4 | import java.io.IOException;
5 | import org.apache.http.HttpResponse;
6 |
7 | public interface Action {
8 |
9 | HttpResponse getResponse(Request r) throws IOException;
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/action/CookieAction.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.action;
2 |
3 | import com.github.paweladamski.httpclientmock.Request;
4 | import java.io.IOException;
5 | import org.apache.http.HttpResponse;
6 | import org.apache.http.client.protocol.HttpClientContext;
7 | import org.apache.http.impl.client.BasicCookieStore;
8 | import org.apache.http.impl.cookie.BasicClientCookie;
9 |
10 | public class CookieAction implements Action {
11 |
12 | private final Action parentAction;
13 | private final String cookieName;
14 | private final String cookieValue;
15 |
16 | public CookieAction(Action parentAction, String cookieName, String cookieValue) {
17 | this.parentAction = parentAction;
18 | this.cookieName = cookieName;
19 | this.cookieValue = cookieValue;
20 | }
21 |
22 | @Override
23 | public HttpResponse getResponse(Request request) throws IOException {
24 | HttpResponse response = parentAction.getResponse(request);
25 |
26 | if (request.getHttpContext() == null) {
27 | throw new RuntimeException("No Http context");
28 | }
29 | if (!(request.getHttpContext() instanceof HttpClientContext)) {
30 | throw new RuntimeException("Http context is not a HttpClientContext instance.");
31 | }
32 | HttpClientContext httpClientContext = (HttpClientContext) request.getHttpContext();
33 | if (httpClientContext.getCookieStore() == null) {
34 | httpClientContext.setCookieStore(new BasicCookieStore());
35 | }
36 | httpClientContext.getCookieStore().addCookie(new BasicClientCookie(cookieName, cookieValue));
37 |
38 | return response;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/action/ExceptionAction.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.action;
2 |
3 | import com.github.paweladamski.httpclientmock.Request;
4 | import java.io.IOException;
5 | import org.apache.http.HttpResponse;
6 |
7 | public class ExceptionAction implements Action {
8 |
9 | private final IOException exception;
10 |
11 | public ExceptionAction(IOException e) {
12 | this.exception = e;
13 | }
14 |
15 | @Override
16 | public HttpResponse getResponse(Request request) throws IOException {
17 | throw exception;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/action/HeaderAction.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.action;
2 |
3 | import com.github.paweladamski.httpclientmock.Request;
4 | import java.io.IOException;
5 | import org.apache.http.HttpResponse;
6 |
7 | public class HeaderAction implements Action {
8 |
9 | private final Action parentAction;
10 | private final String name;
11 | private final String value;
12 |
13 | public HeaderAction(Action parentAction, String name, String value) {
14 | this.parentAction = parentAction;
15 | this.name = name;
16 | this.value = value;
17 | }
18 |
19 | @Override
20 | public HttpResponse getResponse(Request r) throws IOException {
21 | HttpResponse response = parentAction.getResponse(r);
22 | response.addHeader(name, value);
23 | return response;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/action/StatusWithEmptyEntityResponse.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.action;
2 |
3 | import static org.apache.http.HttpStatus.SC_NO_CONTENT;
4 |
5 | import com.github.paweladamski.httpclientmock.Request;
6 | import java.io.IOException;
7 | import java.util.Optional;
8 | import org.apache.http.HttpResponse;
9 | import org.apache.http.ProtocolVersion;
10 | import org.apache.http.entity.StringEntity;
11 | import org.apache.http.message.BasicHttpResponse;
12 |
13 | public class StatusWithEmptyEntityResponse implements Action {
14 |
15 | private final Optional parentAction;
16 | private final int status;
17 | private final String reason;
18 |
19 | public StatusWithEmptyEntityResponse(int status) {
20 | this.status = status;
21 | this.reason = "";
22 | this.parentAction = Optional.empty();
23 | }
24 |
25 | public StatusWithEmptyEntityResponse(Action parentAction, int status) {
26 | this.status = status;
27 | this.reason = "";
28 | this.parentAction = Optional.of(parentAction);
29 | }
30 |
31 | public StatusWithEmptyEntityResponse(Action parentAction, int status, String reason) {
32 | this.status = status;
33 | this.reason = reason;
34 | this.parentAction = Optional.of(parentAction);
35 | }
36 |
37 | @Override
38 | public HttpResponse getResponse(Request request) throws IOException {
39 | HttpResponse response;
40 | if (parentAction.isPresent()) {
41 | response = parentAction.get().getResponse(request);
42 | } else {
43 | response = new BasicHttpResponse(new ProtocolVersion("http", 1, 1), status, "");
44 | if (status != SC_NO_CONTENT) {
45 | response.setEntity(new StringEntity(""));
46 | }
47 | }
48 | response.setStatusCode(status);
49 | response.setReasonPhrase(reason);
50 | return response;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/action/StatusWithNullEntityResponse.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.action;
2 |
3 | import com.github.paweladamski.httpclientmock.Request;
4 | import java.util.Optional;
5 | import org.apache.http.ProtocolVersion;
6 | import org.apache.http.message.BasicHttpResponse;
7 |
8 | public class StatusWithNullEntityResponse implements Action {
9 |
10 | private final Optional reason;
11 | private final int status;
12 |
13 | public StatusWithNullEntityResponse(int status) {
14 | this.status = status;
15 | this.reason = Optional.empty();
16 | }
17 |
18 | public StatusWithNullEntityResponse(int status, String reason) {
19 | this.status = status;
20 | this.reason = Optional.of(reason);
21 | }
22 |
23 | @Override
24 | public BasicHttpResponse getResponse(Request request) {
25 | return new BasicHttpResponse(new ProtocolVersion("http", 1, 1), status, reason.orElse(null));
26 | }
27 | }
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/action/StringResponse.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.action;
2 |
3 | import com.github.paweladamski.httpclientmock.Request;
4 | import java.nio.charset.Charset;
5 | import org.apache.http.HttpResponse;
6 | import org.apache.http.ProtocolVersion;
7 | import org.apache.http.entity.ContentType;
8 | import org.apache.http.entity.StringEntity;
9 | import org.apache.http.message.BasicHttpResponse;
10 |
11 | public class StringResponse implements Action {
12 |
13 | private final int statusCode;
14 | private final String response;
15 | private final Charset charset;
16 | private final ContentType contentType;
17 |
18 | public StringResponse(String response, Charset charset) {
19 | this(200, response, charset);
20 | }
21 |
22 | public StringResponse(int statusCode, String response, Charset charset) {
23 | this(statusCode, response, charset, ContentType.TEXT_PLAIN);
24 | }
25 |
26 | public StringResponse(String response, Charset charset, ContentType contentType) {
27 | this(200, response, charset, contentType);
28 | }
29 |
30 | public StringResponse(int statusCode, String response, Charset charset, ContentType contentType) {
31 | this.statusCode = statusCode;
32 | this.response = response;
33 | this.charset = charset;
34 | this.contentType = contentType;
35 | }
36 |
37 | @Override
38 | public HttpResponse getResponse(Request request) {
39 | BasicHttpResponse response = new BasicHttpResponse(new ProtocolVersion("http", 1, 1), statusCode, "ok");
40 | StringEntity entity = new StringEntity(this.response, this.charset);
41 | entity.setContentType(contentType.toString());
42 | response.setEntity(entity);
43 | response.addHeader("Content-type", contentType.toString());
44 | return response;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/action/UrlEncodedFormEntityResponse.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.action;
2 |
3 | import java.nio.charset.Charset;
4 | import java.util.Collection;
5 |
6 | import org.apache.http.HttpResponse;
7 | import org.apache.http.NameValuePair;
8 | import org.apache.http.ProtocolVersion;
9 | import org.apache.http.client.entity.UrlEncodedFormEntity;
10 | import org.apache.http.message.BasicHttpResponse;
11 |
12 | import com.github.paweladamski.httpclientmock.Request;
13 |
14 | /**
15 | * @author Michael Angstadt
16 | */
17 | public class UrlEncodedFormEntityResponse implements Action {
18 |
19 | private final int statusCode;
20 | private final Collection pairs;
21 | private final Charset charset;
22 |
23 | public UrlEncodedFormEntityResponse(Collection pairs, Charset charset) {
24 | this(200, pairs, charset);
25 | }
26 |
27 | public UrlEncodedFormEntityResponse(int statusCode, Collection pairs, Charset charset) {
28 | this.statusCode = statusCode;
29 | this.pairs = pairs;
30 | this.charset = charset;
31 | }
32 |
33 | @Override
34 | public HttpResponse getResponse(Request request) {
35 | BasicHttpResponse response = new BasicHttpResponse(new ProtocolVersion("http", 1, 1), statusCode, "ok");
36 |
37 | UrlEncodedFormEntity entity = new UrlEncodedFormEntity(pairs, charset);
38 | response.setEntity(entity);
39 |
40 | return response;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/condition/BodyMatcher.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.condition;
2 |
3 | import com.github.paweladamski.httpclientmock.Debugger;
4 | import com.github.paweladamski.httpclientmock.Request;
5 | import java.io.IOException;
6 | import org.apache.http.HttpEntity;
7 | import org.apache.http.HttpEntityEnclosingRequest;
8 | import org.apache.http.HttpRequest;
9 | import org.apache.http.util.EntityUtils;
10 | import org.hamcrest.Matcher;
11 |
12 | public class BodyMatcher implements Condition {
13 |
14 | private final Matcher matcher;
15 |
16 | public BodyMatcher(Matcher matcher) {
17 | this.matcher = matcher;
18 | }
19 |
20 | @Override
21 | public boolean matches(Request request) {
22 | HttpRequest httpRequest = request.getHttpRequest();
23 | if (!(httpRequest instanceof HttpEntityEnclosingRequest)) {
24 | return false;
25 | }
26 |
27 | HttpEntity entity = ((HttpEntityEnclosingRequest) httpRequest).getEntity();
28 | if (entity == null) {
29 | return false;
30 | }
31 |
32 | String message;
33 | try {
34 | message = EntityUtils.toString(entity);
35 | } catch (IOException e) {
36 | return false;
37 | }
38 | return matcher.matches(message);
39 | }
40 |
41 | @Override
42 | public void debug(Request request, Debugger debugger) {
43 | debugger.message(matches(request), "body matches");
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/condition/Condition.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.condition;
2 |
3 | import com.github.paweladamski.httpclientmock.Debugger;
4 | import com.github.paweladamski.httpclientmock.Request;
5 | import org.apache.http.HttpHost;
6 | import org.apache.http.HttpRequest;
7 | import org.apache.http.protocol.HttpContext;
8 |
9 | public interface Condition {
10 |
11 | default boolean matches(HttpHost httpHost, HttpRequest httpRequest, HttpContext httpContext) {
12 | return matches(new Request(httpHost, httpRequest, httpContext));
13 | }
14 |
15 | boolean matches(Request request);
16 |
17 | default void debug(Request request, Debugger debugger) {
18 | debugger.message(matches(request), getClass().getSimpleName());
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/condition/HeaderCondition.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.condition;
2 |
3 | import com.github.paweladamski.httpclientmock.Debugger;
4 | import com.github.paweladamski.httpclientmock.Request;
5 | import org.hamcrest.Matcher;
6 | import org.hamcrest.StringDescription;
7 |
8 | public class HeaderCondition implements Condition {
9 |
10 | private final String header;
11 | private final Matcher value;
12 |
13 | public HeaderCondition(String header, Matcher value) {
14 | this.header = header;
15 | this.value = value;
16 | }
17 |
18 | @Override
19 | public boolean matches(Request request) {
20 | return request.getHttpRequest().getFirstHeader(header) != null &&
21 | value.matches(request.getHttpRequest().getFirstHeader(header).getValue());
22 | }
23 |
24 | @Override
25 | public void debug(Request request, Debugger debugger) {
26 | String matcherDesc = StringDescription.toString(value);
27 | debugger.message(matches(request), "header " + header + " is " + matcherDesc);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/condition/HttpMethodCondition.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.condition;
2 |
3 | import com.github.paweladamski.httpclientmock.Debugger;
4 | import com.github.paweladamski.httpclientmock.Request;
5 |
6 | public class HttpMethodCondition implements Condition {
7 |
8 | private final String method;
9 |
10 | public HttpMethodCondition(String method) {
11 | this.method = method;
12 | }
13 |
14 | @Override
15 | public boolean matches(Request request) {
16 | return request.getHttpRequest().getRequestLine().getMethod().equals(method);
17 | }
18 |
19 | @Override
20 | public void debug(Request request, Debugger debugger) {
21 | debugger.message(matches(request), "HTTP method is " + method);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/condition/UrlEncodedFormCondition.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.condition;
2 |
3 | import com.github.paweladamski.httpclientmock.Debugger;
4 | import com.github.paweladamski.httpclientmock.Request;
5 | import com.github.paweladamski.httpclientmock.matchers.ParametersMatcher;
6 | import java.util.List;
7 | import java.util.Set;
8 | import org.apache.http.NameValuePair;
9 | import org.hamcrest.Matcher;
10 |
11 | /**
12 | * Tests the request body for URL-encoded parameters.
13 | *
14 | * @author Michael Angstadt
15 | */
16 | public class UrlEncodedFormCondition implements Condition {
17 |
18 | private ParametersMatcher expectedParameters = new ParametersMatcher();
19 | private boolean allowExtraParameters = false;
20 |
21 | @Override
22 | public boolean matches(Request r) {
23 | List actualParameters = new UrlEncodedFormParser().parse(r);
24 | if (allowExtraParameters) {
25 | return expectedParameters.matchesAndAllowExtraParameters(actualParameters);
26 | } else {
27 | return expectedParameters.matches(actualParameters);
28 | }
29 | }
30 |
31 | /**
32 | * Adds an expected form parameter.
33 | *
34 | * @param name the parameter name
35 | * @param matcher the expected value
36 | */
37 | public void addExpectedParameter(String name, Matcher matcher) {
38 | expectedParameters.put(name, matcher);
39 | }
40 |
41 | /**
42 | * Adds expected form parameters.
43 | *
44 | * @param parameters the expected parameters
45 | */
46 | public void addExpectedParameters(ParametersMatcher parameters) {
47 | expectedParameters.putAll(parameters);
48 | }
49 |
50 | @Override
51 | public void debug(Request r, Debugger debugger) {
52 | List actual = new UrlEncodedFormParser().parse(r);
53 |
54 | Set missingParams = expectedParameters.findMissingParameters(actual);
55 | for (String param : missingParams) {
56 | debugger.message(false, "form parameter " + param + " is missing from the request");
57 | }
58 |
59 | for (NameValuePair param : actual) {
60 | if (expectedParameters.containsParameter(param.getName())) {
61 | boolean matches = expectedParameters.matches(param.getName(), param.getValue());
62 | String message = "form parameter " + param.getName() + " is " + expectedParameters.get(param.getName()).describe();
63 | debugger.message(matches, message);
64 | } else if (!allowExtraParameters) {
65 | String message = "form parameter " + param.getName() + " was not expected to be in the request";
66 | debugger.message(false, message);
67 | }
68 | }
69 | }
70 |
71 | public void setAllowExtraParameters(boolean allowExtraParameters) {
72 | this.allowExtraParameters = allowExtraParameters;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/condition/UrlEncodedFormParser.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.condition;
2 |
3 | import com.github.paweladamski.httpclientmock.Request;
4 | import java.io.IOException;
5 | import java.util.Collections;
6 | import java.util.List;
7 | import org.apache.http.HttpEntity;
8 | import org.apache.http.HttpEntityEnclosingRequest;
9 | import org.apache.http.NameValuePair;
10 | import org.apache.http.client.utils.URLEncodedUtils;
11 |
12 | public class UrlEncodedFormParser {
13 |
14 | List parse(Request request) {
15 | if (!requestHasBody(request)) {
16 | return Collections.emptyList();
17 | }
18 |
19 | HttpEntityEnclosingRequest httpRequest = (HttpEntityEnclosingRequest) request.getHttpRequest();
20 | HttpEntity entity = httpRequest.getEntity();
21 | if (entity == null) {
22 | return Collections.emptyList();
23 | }
24 |
25 | try {
26 | /*
27 | * The method below returns an empty list if the Content-Type of the
28 | * request is not "application/x-www-form-urlencoded". So, requests with
29 | * other kinds of data in the body will correctly be ignored here.
30 | */
31 | return URLEncodedUtils.parse(entity);
32 | } catch (IOException e) {
33 | throw new RuntimeException(e);
34 | }
35 | }
36 |
37 | private boolean requestHasBody(Request r) {
38 | return (r.getHttpRequest() instanceof HttpEntityEnclosingRequest);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/matchers/HttpResponseMatchers.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.matchers;
2 |
3 | import java.io.IOException;
4 | import java.util.Optional;
5 | import org.apache.http.HttpResponse;
6 | import org.apache.http.client.CookieStore;
7 | import org.apache.http.client.protocol.HttpClientContext;
8 | import org.apache.http.cookie.Cookie;
9 | import org.apache.http.util.EntityUtils;
10 | import org.hamcrest.BaseMatcher;
11 | import org.hamcrest.Description;
12 | import org.hamcrest.Matcher;
13 |
14 | public final class HttpResponseMatchers {
15 |
16 | public static Matcher super HttpResponse> hasStatus(int expectedStatus) {
17 | return new BaseMatcher() {
18 | public boolean matches(Object o) {
19 | HttpResponse response = (HttpResponse) o;
20 | return response.getStatusLine().getStatusCode() == expectedStatus;
21 | }
22 |
23 | public void describeTo(Description description) {
24 | description.appendValue(expectedStatus);
25 | }
26 | };
27 | }
28 |
29 | public static Matcher super HttpResponse> hasNoEntity() {
30 | return new BaseMatcher() {
31 | public boolean matches(Object o) {
32 | HttpResponse response = (HttpResponse) o;
33 | return response.getEntity() == null;
34 | }
35 |
36 | public void describeTo(Description description) {
37 | description.appendValue(null);
38 | }
39 | };
40 | }
41 |
42 | public static Matcher super HttpResponse> hasReason(String expectedReason) {
43 | return new BaseMatcher() {
44 | public boolean matches(Object o) {
45 | HttpResponse response = (HttpResponse) o;
46 | return response.getStatusLine().getReasonPhrase().equals(expectedReason);
47 | }
48 |
49 | public void describeTo(Description description) {
50 | description.appendValue(expectedReason);
51 | }
52 | };
53 | }
54 |
55 | public static Matcher super HttpResponse> hasContent(final String content) {
56 | return hasContent(content, "UTF-8");
57 | }
58 |
59 | public static Matcher super HttpResponse> hasContent(final String content, final String charset) {
60 | return new BaseMatcher() {
61 | public boolean matches(Object o) {
62 | HttpResponse response = (HttpResponse) o;
63 |
64 | String targetString;
65 | try {
66 | byte[] bytes = EntityUtils.toByteArray(response.getEntity());
67 | targetString = new String(bytes, charset);
68 | } catch (IOException e) {
69 | e.printStackTrace();
70 | return false;
71 | }
72 |
73 | return targetString.equals(content);
74 | }
75 |
76 | public void describeTo(Description description) {
77 | description.appendText(content);
78 | }
79 | };
80 | }
81 |
82 | public static Matcher super HttpClientContext> hasCookie(final String expectedCookieName, final String expectedCookieValue) {
83 | return new BaseMatcher() {
84 | public boolean matches(Object o) {
85 | HttpClientContext httpClientContext = (HttpClientContext) o;
86 | String cookieValue = getCookieValue(httpClientContext.getCookieStore(), expectedCookieName);
87 | return expectedCookieValue.equals(cookieValue);
88 | }
89 |
90 | public void describeTo(Description description) {
91 | description.appendValue(expectedCookieValue);
92 | }
93 |
94 | private String getCookieValue(CookieStore cookieStore, String cookieName) {
95 | if (cookieStore == null) {
96 | return null;
97 | }
98 |
99 | return cookieStore.getCookies().stream()
100 | .filter(c -> c.getName().equalsIgnoreCase(cookieName))
101 | .findFirst().map(c -> c.getValue()).orElse(null);
102 | }
103 | };
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/matchers/MatchersList.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.matchers;
2 |
3 | import java.util.ArrayList;
4 | import org.hamcrest.Matcher;
5 | import org.hamcrest.StringDescription;
6 |
7 | public class MatchersList extends ArrayList> {
8 |
9 | public boolean allMatches(T value) {
10 | return this.stream()
11 | .allMatch(m -> m.matches(value));
12 | }
13 |
14 | public String describe() {
15 | return this.stream().map(StringDescription::toString).reduce((a, b) -> a + " and " + b).orElse("");
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/matchers/ParametersMatcher.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.matchers;
2 |
3 | import java.util.HashMap;
4 | import java.util.List;
5 | import java.util.Set;
6 | import java.util.function.Predicate;
7 | import java.util.stream.Collectors;
8 | import org.apache.http.NameValuePair;
9 | import org.hamcrest.Matcher;
10 |
11 | public class ParametersMatcher {
12 |
13 | private HashMap> matchers = new HashMap<>();
14 |
15 | public void put(String name, Matcher value) {
16 | matchers.computeIfAbsent(name, n -> new MatchersList<>()).add(value);
17 | }
18 |
19 | public void putAll(String name, MatchersList value) {
20 | matchers.computeIfAbsent(name, n -> new MatchersList<>()).addAll(value);
21 | }
22 |
23 | public MatchersList get(String name) {
24 | return matchers.get(name);
25 | }
26 |
27 | public boolean containsParameter(String name) {
28 | return matchers.containsKey(name);
29 | }
30 |
31 | public void putAll(ParametersMatcher parametersMatcher) {
32 | for (String paramName : parametersMatcher.matchers.keySet()) {
33 | putAll(paramName, parametersMatcher.matchers.get(paramName));
34 | }
35 | }
36 |
37 | public boolean matchesAndAllowExtraParameters(List actual) {
38 | return findMissingParameters(actual).isEmpty()
39 | && allParametersHaveMatchingValue(actual);
40 | }
41 |
42 | public boolean matches(List actual) {
43 | return findRedundantParams(actual).isEmpty()
44 | && findMissingParameters(actual).isEmpty()
45 | && allParametersHaveMatchingValue(actual);
46 | }
47 |
48 | public boolean matches(String name, String value) {
49 | return matchers.containsKey(name) && matchers.get(name).allMatches(value);
50 | }
51 |
52 | private boolean allParametersHaveMatchingValue(List actual) {
53 | return actual.stream().allMatch(param -> matchers.getOrDefault(param.getName(), new MatchersList<>()).allMatches(param.getValue()));
54 | }
55 |
56 | public Set findRedundantParams(List actualParameters) {
57 | return actualParameters.stream()
58 | .map(NameValuePair::getName)
59 | .filter(n -> !matchers.containsKey(n))
60 | .collect(Collectors.toSet());
61 | }
62 |
63 | public Set findMissingParameters(List actualParameters) {
64 | List actualParametersName = actualParameters.stream().map(NameValuePair::getName).collect(Collectors.toList());
65 | return matchers.keySet().stream()
66 | .filter(((Predicate) actualParametersName::contains).negate())
67 | .collect(Collectors.toSet());
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/github/paweladamski/httpclientmock/matchers/UrlQueryMatcher.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.matchers;
2 |
3 | import com.github.paweladamski.httpclientmock.Debugger;
4 | import com.github.paweladamski.httpclientmock.UrlParamsParser;
5 | import java.util.List;
6 | import java.util.Set;
7 | import org.apache.http.NameValuePair;
8 | import org.hamcrest.Matcher;
9 |
10 | public class UrlQueryMatcher {
11 |
12 | private ParametersMatcher expected = new ParametersMatcher();
13 | private boolean allowExtraParameters;
14 |
15 | public boolean matches(String query) {
16 | List actualParameters = new UrlParamsParser().parse(query);
17 | if (allowExtraParameters) {
18 | return expected.matchesAndAllowExtraParameters(actualParameters);
19 | } else {
20 | return expected.matches(actualParameters);
21 | }
22 | }
23 |
24 | public void put(String name, Matcher matcher) {
25 | expected.put(name, matcher);
26 | }
27 |
28 | public void describe(String query, Debugger debugger) {
29 | List actualParameters = new UrlParamsParser().parse(query);
30 | Set missingParams = expected.findMissingParameters(actualParameters);
31 | for (String param : missingParams) {
32 | debugger.message(false, "query parameter " + param + " is missing from the request");
33 | }
34 |
35 | for (NameValuePair param : actualParameters) {
36 | if (expected.containsParameter(param.getName())) {
37 | boolean matches = expected.matches(param.getName(), param.getValue());
38 | String message = "query parameter " + param.getName() + " is " + expected.get(param.getName()).describe();
39 | debugger.message(matches, message);
40 | } else if (!allowExtraParameters){
41 | String message = "query parameter " + param.getName() + " was not expected to be in the request";
42 | debugger.message(false, message);
43 | }
44 | }
45 | }
46 |
47 | public void setAllowExtraParameters(boolean allowExtraParameters) {
48 | this.allowExtraParameters = allowExtraParameters;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/Asserts.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import org.junit.jupiter.api.Assertions;
4 |
5 | @SuppressWarnings("unchecked")
6 | class Asserts {
7 |
8 | static T assertThrows(Class expected, ThrowingRunnable action) throws Exception {
9 | try {
10 | action.run();
11 | Assertions.fail("Did not throw expected " + expected.getSimpleName());
12 | return null; // never actually
13 | } catch (Exception actual) {
14 | if (!expected.isAssignableFrom(actual.getClass())) { // runtime '!(actual instanceof expected)'
15 | System.err.println("Threw " + actual.getClass().getSimpleName()
16 | + ", which is not a subtype of expected "
17 | + expected.getSimpleName());
18 | throw actual; // throw the unexpected Throwable for maximum transparency
19 | } else {
20 | return (T) actual; // return the expected Throwable for further examination
21 | }
22 | }
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/DebuggingTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static com.github.paweladamski.httpclientmock.Requests.httpGet;
4 | import static com.github.paweladamski.httpclientmock.Requests.httpPost;
5 | import static org.hamcrest.MatcherAssert.assertThat;
6 | import static org.hamcrest.Matchers.hasItem;
7 | import static org.hamcrest.Matchers.not;
8 | import static org.junit.jupiter.api.Assertions.assertFalse;
9 | import static org.junit.jupiter.api.Assertions.assertTrue;
10 |
11 | import java.io.IOException;
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.List;
15 | import org.apache.http.client.entity.UrlEncodedFormEntity;
16 | import org.apache.http.client.methods.HttpGet;
17 | import org.apache.http.client.methods.HttpPost;
18 | import org.apache.http.message.BasicNameValuePair;
19 | import org.hamcrest.Matchers;
20 | import org.junit.jupiter.api.BeforeEach;
21 | import org.junit.jupiter.api.Test;
22 |
23 | public class DebuggingTest {
24 |
25 | private HttpClientMock httpClientMock;
26 | private TestDebugger debugger;
27 |
28 | @BeforeEach
29 | public void setUp() {
30 | debugger = new TestDebugger();
31 | httpClientMock = new HttpClientMock("http://localhost", debugger);
32 | }
33 |
34 | @Test
35 | public void should_print_all_request_with_no_matching_rules() throws IOException {
36 | httpClientMock.onGet("/admin").doReturn("admin");
37 |
38 | httpClientMock.execute(new HttpGet("http://localhost/login"));
39 | httpClientMock.execute(new HttpGet("http://localhost/admin"));
40 |
41 | assertThat(debugger.requests, hasItem("http://localhost/login"));
42 | assertThat(debugger.requests, not(hasItem("http://localhost/admin")));
43 | }
44 |
45 | @Test
46 | public void should_print_all_request_when_debugging_is_turn_on() throws IOException {
47 | httpClientMock.onGet("/login").doReturn("login");
48 | httpClientMock.onGet("/user").doReturn("user");
49 | httpClientMock.onGet("/admin").doReturn("admin");
50 |
51 | httpClientMock.debugOn();
52 | httpClientMock.execute(new HttpGet("http://localhost/login"));
53 | httpClientMock.execute(new HttpGet("http://localhost/user"));
54 | httpClientMock.debugOff();
55 | httpClientMock.execute(new HttpGet("http://localhost/admin"));
56 |
57 | assertThat(debugger.requests, hasItem("http://localhost/login"));
58 | assertThat(debugger.requests, hasItem("http://localhost/user"));
59 | assertThat(debugger.requests, not(hasItem("http://localhost/admin")));
60 | }
61 |
62 | @Test
63 | public void should_debug_header_condition() throws IOException {
64 | httpClientMock
65 | .onGet("/login").withHeader("User-Agent", "Mozilla")
66 | .doReturn("mozilla");
67 |
68 | HttpGet getMozilla = new HttpGet("http://localhost/login");
69 | HttpGet getChrome = new HttpGet("http://localhost/login");
70 | getMozilla.addHeader("User-Agent", "Mozilla");
71 | getChrome.addHeader("User-Agent", "Chrome");
72 |
73 | httpClientMock.debugOn();
74 | httpClientMock.execute(getMozilla);
75 | httpClientMock.execute(getChrome);
76 | httpClientMock.debugOff();
77 |
78 | assertTrue(debugger.matching.contains("header User-Agent is \"Mozilla\""));
79 | assertFalse(debugger.notMatching.contains("header User-Agent is \"Chrome\""));
80 | }
81 |
82 | @Test
83 | public void should_put_message_about_missing_parameter() throws IOException {
84 | httpClientMock.onGet("/login?foo=bar");
85 | httpClientMock.execute(httpGet("http://localhost/login"));
86 | assertTrue(debugger.notMatching.contains("query parameter foo is missing from the request"));
87 | }
88 |
89 | @Test
90 | public void should_put_message_about_matching_parameter() throws IOException {
91 | httpClientMock
92 | .onGet("/login").withParameter("foo", "bar")
93 | .doReturn("login");
94 | httpClientMock.debugOn();
95 | httpClientMock.execute(httpGet("http://localhost/login?foo=bar"));
96 | assertTrue(debugger.matching.contains("query parameter foo is \"bar\""));
97 | }
98 |
99 | @Test
100 | public void should_put_message_about_not_matching_parameter() throws IOException {
101 | httpClientMock.onGet("/login")
102 | .withParameter("foo", "bar")
103 | .doReturn("login");
104 | httpClientMock.execute(httpGet("http://localhost/login?foo=bbb"));
105 | assertTrue(debugger.notMatching.contains("query parameter foo is \"bar\""));
106 | }
107 |
108 | @Test
109 | public void should_put_message_about_redundant_parameter() throws IOException {
110 | httpClientMock.onGet("/login")
111 | .withoutExtraParameters()
112 | .doReturn("login");
113 | httpClientMock.execute(httpGet("http://localhost/login?foo=bbb"));
114 | assertTrue(debugger.notMatching.contains("query parameter foo was not expected to be in the request"));
115 | }
116 |
117 | @Test
118 | public void should_put_message_with_all_parameter_matchers() throws IOException {
119 | httpClientMock.onGet("/login")
120 | .withParameter("foo", Matchers.startsWith("a"))
121 | .withParameter("foo", Matchers.endsWith("b"))
122 | .doReturn("login");
123 | httpClientMock.debugOn();
124 | httpClientMock.execute(httpGet("http://localhost/login?foo=aabb"));
125 | assertTrue(debugger.matching.contains("query parameter foo is a string starting with \"a\" and a string ending with \"b\""));
126 | }
127 |
128 | @Test
129 | public void should_put_message_about_not_matching_reference() throws IOException {
130 | httpClientMock.onGet("/login#foo")
131 | .doReturn("login");
132 | httpClientMock.execute(httpGet("http://localhost/login"));
133 | assertTrue(debugger.notMatching.contains("reference is \"foo\""));
134 | }
135 |
136 | @Test
137 | public void should_put_message_about_matching_reference() throws IOException {
138 | httpClientMock.onGet("/login#foo")
139 | .doReturn("login");
140 | httpClientMock.debugOn();
141 | httpClientMock.execute(httpGet("http://localhost/login#foo"));
142 | assertTrue(debugger.matching.contains("reference is \"foo\""));
143 | }
144 |
145 | @Test
146 | public void should_not_put_message_about_reference_when_it_is_not_used() throws IOException {
147 | httpClientMock.onGet("/login").doReturn("login");
148 | httpClientMock.debugOn();
149 | httpClientMock.execute(httpGet("http://localhost/login"));
150 | assertTrue(debugger.matching.stream().noneMatch(s -> s.startsWith("reference")));
151 | assertTrue(debugger.notMatching.stream().noneMatch(s -> s.startsWith("reference")));
152 | }
153 |
154 | @Test
155 | public void should_put_message_about_matching_http_method() throws IOException {
156 | httpClientMock.onGet("/login").doReturn("login");
157 | httpClientMock.debugOn();
158 | httpClientMock.execute(httpGet("http://localhost/login"));
159 | assertTrue(debugger.matching.contains("HTTP method is GET"));
160 | }
161 |
162 | @Test
163 | public void should_put_message_about_not_matching_http_method() throws IOException {
164 | httpClientMock.onGet("/login").doReturn("login");
165 | httpClientMock.debugOn();
166 | httpClientMock.execute(httpPost("http://localhost/login"));
167 | assertTrue(debugger.notMatching.contains("HTTP method is GET"));
168 | }
169 |
170 | @Test
171 | public void should_put_message_about_not_matching_URL() throws IOException {
172 | httpClientMock.onGet("http://localhost:8080/login").doReturn("login");
173 | httpClientMock.debugOn();
174 | httpClientMock.execute(httpPost("https://www.google.com"));
175 | assertTrue(debugger.notMatching.contains("schema is \"http\""));
176 | assertTrue(debugger.notMatching.contains("host is \"localhost\""));
177 | assertTrue(debugger.notMatching.contains("path is \"/login\""));
178 | assertTrue(debugger.notMatching.contains("port is <8080>"));
179 | }
180 |
181 | @Test
182 | public void should_put_message_about_matching_URL() throws IOException {
183 | httpClientMock.onGet("http://localhost:8080/login").doReturn("login");
184 | httpClientMock.debugOn();
185 | httpClientMock.execute(httpPost("http://localhost:8080/login"));
186 | assertTrue(debugger.matching.contains("schema is \"http\""));
187 | assertTrue(debugger.matching.contains("host is \"localhost\""));
188 | assertTrue(debugger.matching.contains("path is \"/login\""));
189 | assertTrue(debugger.matching.contains("port is <8080>"));
190 | }
191 |
192 | @Test
193 | public void should_not_put_message_not_expected_query_parameters_when_ExtraParametersAreAllowed() throws IOException {
194 | httpClientMock.onGet("http://localhost:8080/login")
195 | .withExtraParameters()
196 | .doReturn("login");
197 | httpClientMock.debugOn();
198 | httpClientMock.execute(httpPost("http://localhost:8080/login?foo=bar"));
199 | assertFalse(debugger.notMatching.contains("query parameter foo was not expected to be in the request"));
200 | }
201 |
202 | @Test
203 | public void should_put_message_not_expected_form_parameters_when_ExtraParametersAreDisAllowed() throws IOException {
204 | httpClientMock.onPost("http://localhost:8080/login")
205 | .withoutExtraFormParameters()
206 | .doReturn("login");
207 | httpClientMock.debugOn();
208 |
209 | HttpPost request = new HttpPost("http://localhost/login");
210 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
211 | new BasicNameValuePair("foo", "bar")
212 | )));
213 | httpClientMock.execute(request);
214 | assertTrue(debugger.notMatching.contains("form parameter foo was not expected to be in the request"));
215 | }
216 |
217 | @Test
218 | public void should_not_put_message_not_expected_form_parameters_when_ExtraParametersAreAllowed() throws IOException {
219 | httpClientMock.onPost("http://localhost:8080/login")
220 | .withExtraFormParameters()
221 | .doReturn("login");
222 | httpClientMock.debugOn();
223 |
224 | HttpPost request = new HttpPost("http://localhost/login");
225 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
226 | new BasicNameValuePair("foo", "bar")
227 | )));
228 | httpClientMock.execute(request);
229 | assertFalse(debugger.notMatching.contains("form parameter foo was not expected to be in the request"));
230 | }
231 |
232 | }
233 |
234 | class TestDebugger extends Debugger {
235 |
236 | public final ArrayList matching = new ArrayList<>();
237 | public final ArrayList notMatching = new ArrayList<>();
238 | public final ArrayList requests = new ArrayList<>();
239 |
240 | @Override
241 | public Rule debug(List rules, Request request) {
242 | this.requests.add(request.getUri());
243 | return super.debug(rules, request);
244 | }
245 |
246 | @Override
247 | public void message(boolean matching, String expected) {
248 | super.message(matching, expected);
249 | if (matching) {
250 | this.matching.add(expected);
251 | } else {
252 | this.notMatching.add(expected);
253 | }
254 | }
255 | }
256 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/HttpClientMockBuilderTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static com.github.paweladamski.httpclientmock.Requests.httpPost;
4 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasContent;
5 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasStatus;
6 | import static org.hamcrest.MatcherAssert.assertThat;
7 | import static org.hamcrest.Matchers.containsString;
8 |
9 | import com.github.paweladamski.httpclientmock.condition.Condition;
10 | import com.github.paweladamski.httpclientmock.matchers.ParametersMatcher;
11 | import java.io.IOException;
12 | import java.util.Arrays;
13 | import java.util.Collections;
14 | import org.apache.http.HttpHost;
15 | import org.apache.http.HttpResponse;
16 | import org.apache.http.client.entity.UrlEncodedFormEntity;
17 | import org.apache.http.client.methods.HttpDelete;
18 | import org.apache.http.client.methods.HttpGet;
19 | import org.apache.http.client.methods.HttpHead;
20 | import org.apache.http.client.methods.HttpOptions;
21 | import org.apache.http.client.methods.HttpPatch;
22 | import org.apache.http.client.methods.HttpPost;
23 | import org.apache.http.client.methods.HttpPut;
24 | import org.apache.http.message.BasicNameValuePair;
25 | import org.hamcrest.Matchers;
26 | import org.junit.jupiter.api.Test;
27 |
28 | public class HttpClientMockBuilderTest {
29 |
30 | @Test
31 | public void shouldMatchSeparateHostAndPath() throws IOException {
32 | HttpClientMock httpClientMock = new HttpClientMock();
33 |
34 | httpClientMock.onPost()
35 | .withHost("http://localhost")
36 | .withPath("/login")
37 | .doReturnStatus(200);
38 |
39 | HttpResponse ok = httpClientMock.execute(new HttpPost("http://localhost/login"));
40 | assertThat(ok, hasStatus(200));
41 | }
42 |
43 | @Test
44 | public void shouldMatchSeparatePathAndParameter() throws IOException {
45 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
46 |
47 | httpClientMock.onPost()
48 | .withPath("/login")
49 | .withParameter("a", "1")
50 | .doReturn("one");
51 | httpClientMock.onPost()
52 | .withPath("/login")
53 | .withParameter("b", "2")
54 | .withExtraParameters()
55 | .doReturn("two");
56 |
57 | HttpResponse one = httpClientMock.execute(new HttpPost("http://localhost/login?a=1"));
58 | HttpResponse two = httpClientMock.execute(new HttpPost("http://localhost/login?b=2"));
59 | HttpResponse three = httpClientMock.execute(new HttpPost("http://localhost/login?a=1&b=2"));
60 | assertThat(one, hasContent("one"));
61 | assertThat(two, hasContent("two"));
62 | assertThat(three, hasContent("two"));
63 | }
64 |
65 | @Test
66 | public void shouldUseRightMethod() throws IOException {
67 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
68 |
69 | httpClientMock.onGet("/foo").doReturn("get");
70 | httpClientMock.onPost("/foo").doReturn("post");
71 | httpClientMock.onPut("/foo").doReturn("put");
72 | httpClientMock.onDelete("/foo").doReturn("delete");
73 | httpClientMock.onHead("/foo").doReturn("head");
74 | httpClientMock.onOptions("/foo").doReturn("options");
75 | httpClientMock.onPatch("/foo").doReturn("patch");
76 |
77 | HttpResponse getResponse = httpClientMock.execute(new HttpGet("http://localhost/foo"));
78 | HttpResponse postResponse = httpClientMock.execute(new HttpPost("http://localhost/foo"));
79 | HttpResponse putResponse = httpClientMock.execute(new HttpPut("http://localhost/foo"));
80 | HttpResponse deleteResponse = httpClientMock.execute(new HttpDelete("http://localhost/foo"));
81 | HttpResponse headResponse = httpClientMock.execute(new HttpHead("http://localhost/foo"));
82 | HttpResponse optionsResponse = httpClientMock.execute(new HttpOptions("http://localhost/foo"));
83 | HttpResponse patchResponse = httpClientMock.execute(new HttpPatch("http://localhost/foo"));
84 |
85 | assertThat(getResponse, hasContent("get"));
86 | assertThat(postResponse, hasContent("post"));
87 | assertThat(putResponse, hasContent("put"));
88 | assertThat(deleteResponse, hasContent("delete"));
89 | assertThat(headResponse, hasContent("head"));
90 | assertThat(optionsResponse, hasContent("options"));
91 | assertThat(patchResponse, hasContent("patch"));
92 | }
93 |
94 | @Test
95 | public void should_check_custom_rule() throws IOException {
96 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
97 |
98 | Condition fooCondition = (request) -> request.getUri().contains("foo");
99 |
100 | httpClientMock.onGet("http://localhost/foo/bar")
101 | .with(fooCondition)
102 | .doReturn("yes");
103 |
104 | HttpResponse first = httpClientMock.execute(new HttpGet("http://localhost/foo/bar"));
105 |
106 | assertThat(first, hasContent("yes"));
107 | }
108 |
109 | @Test
110 | public void should_use_right_host_and_path() throws IOException {
111 | HttpClientMock httpClientMock = new HttpClientMock();
112 |
113 | httpClientMock.onGet("http://localhost:8080/foo").doReturn("localhost");
114 | httpClientMock.onGet("http://www.google.com").doReturn("google");
115 | httpClientMock.onGet("https://www.google.com").doReturn("https");
116 |
117 | HttpResponse localhost = httpClientMock.execute(new HttpGet("http://localhost:8080/foo"));
118 | HttpResponse google = httpClientMock.execute(new HttpGet("http://www.google.com"));
119 | HttpResponse https = httpClientMock.execute(new HttpGet("https://www.google.com"));
120 |
121 | assertThat(localhost, hasContent("localhost"));
122 | assertThat(google, hasContent("google"));
123 | assertThat(https, hasContent("https"));
124 | }
125 |
126 | @Test
127 | public void should_match_right_header_value() throws IOException {
128 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
129 |
130 | httpClientMock
131 | .onGet("/login").withHeader("User-Agent", "Mozilla")
132 | .doReturn("mozilla");
133 | httpClientMock
134 | .onGet("/login").withHeader("User-Agent", "Chrome")
135 | .doReturn("chrome");
136 |
137 | HttpGet getMozilla = new HttpGet("http://localhost:8080/login");
138 | HttpGet getChrome = new HttpGet("http://localhost:8080/login");
139 | HttpGet getSafari = new HttpGet("http://localhost:8080/login");
140 | getMozilla.addHeader("User-Agent", "Mozilla");
141 | getChrome.addHeader("User-Agent", "Chrome");
142 | getSafari.addHeader("User-Agent", "Safari");
143 |
144 | assertThat(httpClientMock.execute(getMozilla), hasContent("mozilla"));
145 | assertThat(httpClientMock.execute(getChrome), hasContent("chrome"));
146 | assertThat(httpClientMock.execute(getSafari), hasStatus(404));
147 | }
148 |
149 | @Test
150 | public void should_match_right_parameter_value() throws IOException {
151 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
152 |
153 | httpClientMock
154 | .onGet("/foo").withParameter("id", "1").withParameter("name", "abc")
155 | .doReturn("one");
156 | httpClientMock
157 | .onGet("/foo").withParameter("id", "2")
158 | .doReturn("two");
159 |
160 | HttpResponse one = httpClientMock.execute(new HttpGet("http://localhost:8080/foo?id=1&name=abc"));
161 | HttpResponse two = httpClientMock.execute(new HttpGet("http://localhost:8080/foo?id=2"));
162 |
163 | assertThat(one, hasContent("one"));
164 | assertThat(two, hasContent("two"));
165 | }
166 |
167 | @Test
168 | public void should_add_default_host_to_every_relative_path() throws IOException {
169 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
170 |
171 | httpClientMock.onGet("/login").doReturn("login");
172 | httpClientMock.onGet("/product/search").doReturn("search");
173 | httpClientMock.onGet("/logout").doReturn("logout");
174 |
175 | HttpResponse login = httpClientMock.execute(new HttpGet("http://localhost:8080/login"));
176 | HttpResponse search = httpClientMock.execute(new HttpGet("http://localhost:8080/product/search"));
177 | HttpResponse logout = httpClientMock.execute(new HttpGet("http://localhost:8080/logout"));
178 |
179 | assertThat(login, hasContent("login"));
180 | assertThat(search, hasContent("search"));
181 | assertThat(logout, hasContent("logout"));
182 |
183 | }
184 |
185 | @Test
186 | public void checkBody() throws IOException {
187 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
188 |
189 | httpClientMock.onPost("/login")
190 | .doReturnStatus(500);
191 | httpClientMock.onPost("/login").withBody(containsString("foo"))
192 | .doReturnStatus(200);
193 |
194 | HttpResponse badLogin = httpClientMock.execute(new HttpPost("http://localhost:8080/login"));
195 | HttpResponse correctLogin = httpClientMock.execute(httpPost("http://localhost:8080/login", "foo"));
196 |
197 | assertThat(correctLogin, hasStatus(200));
198 | assertThat(badLogin, hasStatus(500));
199 | }
200 |
201 | @Test
202 | public void when_url_contains_parameter_it_should_be_added_us_a_separate_condition() throws IOException {
203 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
204 |
205 | httpClientMock.onPost("/login?user=john")
206 | .withoutExtraParameters()
207 | .doReturnStatus(400);
208 | httpClientMock.onPost("/login?user=john&pass=abc")
209 | .withoutExtraParameters()
210 | .doReturnStatus(200);
211 |
212 | HttpResponse notFound = httpClientMock.execute(new HttpPost("http://localhost/login"));
213 | HttpResponse wrong = httpClientMock.execute(new HttpPost("http://localhost/login?user=john"));
214 | HttpResponse ok = httpClientMock.execute(new HttpPost("http://localhost/login?user=john&pass=abc"));
215 | HttpResponse notFound_2 = httpClientMock.execute(new HttpPost("http://localhost/login?user=john&pass=abc&foo=bar"));
216 |
217 | assertThat(notFound, hasStatus(404));
218 | assertThat(wrong, hasStatus(400));
219 | assertThat(ok, hasStatus(200));
220 | assertThat(notFound_2, hasStatus(404));
221 | }
222 |
223 | @Test
224 | public void when_url_contains_reference_it_should_be_added_us_a_separate_condition() throws IOException {
225 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
226 |
227 | httpClientMock.onPost("/login")
228 | .doReturnStatus(400);
229 | httpClientMock.onPost("/login#abc")
230 | .doReturnStatus(200);
231 |
232 | HttpResponse wrong = httpClientMock.execute(new HttpPost("http://localhost/login"));
233 | HttpResponse ok = httpClientMock.execute(new HttpPost("http://localhost/login#abc"));
234 |
235 | assertThat(wrong, hasStatus(400));
236 | assertThat(ok, hasStatus(200));
237 | }
238 |
239 | @Test
240 | public void should_handle_path_with_parameters_and_reference() throws IOException {
241 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
242 |
243 | httpClientMock.onPost("/login?p=1#abc")
244 | .doReturnStatus(200);
245 |
246 | HttpResponse wrong1 = httpClientMock.execute(new HttpPost("http://localhost/login"));
247 | HttpResponse wrong2 = httpClientMock.execute(new HttpPost("http://localhost/login?p=1"));
248 | HttpResponse wrong3 = httpClientMock.execute(new HttpPost("http://localhost/login#abc"));
249 | HttpResponse ok = httpClientMock.execute(new HttpPost("http://localhost/login?p=1#abc"));
250 |
251 | assertThat(wrong1, hasStatus(404));
252 | assertThat(wrong2, hasStatus(404));
253 | assertThat(wrong3, hasStatus(404));
254 | assertThat(ok, hasStatus(200));
255 | }
256 |
257 | @Test
258 | public void should_check_reference_value() throws IOException {
259 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
260 |
261 | httpClientMock.onPost("/login")
262 | .doReturnStatus(400);
263 | httpClientMock.onPost("/login")
264 | .withReference("ref")
265 | .doReturnStatus(200);
266 |
267 | HttpResponse wrong = httpClientMock.execute(new HttpPost("http://localhost/login"));
268 | HttpResponse ok = httpClientMock.execute(new HttpPost("http://localhost/login#ref"));
269 |
270 | assertThat(wrong, hasStatus(400));
271 | assertThat(ok, hasStatus(200));
272 | }
273 |
274 | @Test
275 | public void after_reset_every_call_should_result_in_status_404() throws IOException {
276 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
277 |
278 | httpClientMock.onPost("/login").doReturnStatus(200);
279 | httpClientMock.reset();
280 | HttpResponse login = httpClientMock.execute(new HttpPost("http://localhost/login"));
281 |
282 | assertThat(login, hasStatus(404));
283 | }
284 |
285 | @Test
286 | public void after_execute_and_reset_every_call_should_result_in_status_404() throws IOException {
287 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
288 |
289 | httpClientMock.onPost("/login").doReturnStatus(200);
290 | httpClientMock.execute(new HttpPost("http://localhost/login"));
291 | httpClientMock.reset();
292 | HttpResponse login = httpClientMock.execute(new HttpPost("http://localhost/login"));
293 |
294 | assertThat(login, hasStatus(404));
295 | }
296 |
297 | @Test
298 | public void after_reset_number_of_calls_should_be_zero() throws IOException {
299 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
300 |
301 | httpClientMock.onPost("/login").doReturnStatus(200);
302 | httpClientMock.execute(new HttpPost("http://localhost/login"));
303 | httpClientMock.execute(new HttpPost("http://localhost/login"));
304 | httpClientMock.reset();
305 | httpClientMock.verify().post("/login").notCalled();
306 |
307 | httpClientMock.onPost("/login").doReturnStatus(200);
308 | httpClientMock.execute(new HttpPost("http://localhost/login"));
309 | httpClientMock.execute(new HttpPost("http://localhost/login"));
310 | httpClientMock.verify().post("/login").called(2);
311 |
312 | }
313 |
314 | @Test
315 | public void not_all_parameters_occurred() throws IOException {
316 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
317 |
318 | httpClientMock.onPost("/login")
319 | .withParameter("foo", "bar")
320 | .doReturnStatus(200);
321 |
322 | HttpResponse response = httpClientMock.execute(new HttpPost("http://localhost/login"));
323 | assertThat(response, hasStatus(404));
324 | }
325 |
326 | @Test
327 | public void should_allow_different_host_then_default() throws IOException {
328 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
329 |
330 | httpClientMock.onGet("/login").doReturn("login");
331 | httpClientMock.onGet("http://www.google.com").doReturn("google");
332 |
333 | HttpResponse login = httpClientMock.execute(new HttpGet("http://localhost/login"));
334 | HttpResponse google = httpClientMock.execute(new HttpGet("http://www.google.com"));
335 | assertThat(login, hasContent("login"));
336 | assertThat(google, hasContent("google"));
337 | }
338 |
339 | @Test
340 | public void withFormParameter() throws IOException {
341 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
342 |
343 | httpClientMock.onPost("/login")
344 | .withFormParameter("username", "John")
345 | .withFormParameter("password", Matchers.containsString("secret"))
346 | .doReturnStatus(200);
347 |
348 | HttpPost request = new HttpPost("http://localhost/login");
349 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
350 | new BasicNameValuePair("username", "John"),
351 | new BasicNameValuePair("password", "secret!")
352 | )));
353 | HttpResponse response = httpClientMock.execute(request);
354 | assertThat(response, hasStatus(200));
355 |
356 | request = new HttpPost("http://localhost/login");
357 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
358 | new BasicNameValuePair("username", "John"),
359 | new BasicNameValuePair("password", "wrong")
360 | )));
361 | response = httpClientMock.execute(request);
362 | assertThat(response, hasStatus(404));
363 | }
364 |
365 | @Test
366 | public void withFormParameters() throws IOException {
367 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
368 |
369 | ParametersMatcher parameters = new ParametersMatcher();
370 | parameters.put("username", Matchers.equalTo("John"));
371 | parameters.put("password", Matchers.containsString("secret"));
372 |
373 | httpClientMock.onPost("/login")
374 | .withFormParameters(parameters)
375 | .doReturnStatus(200);
376 |
377 | HttpPost request = new HttpPost("http://localhost/login");
378 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
379 | new BasicNameValuePair("username", "John"),
380 | new BasicNameValuePair("password", "secret!")
381 | )));
382 | HttpResponse response = httpClientMock.execute(request);
383 | assertThat(response, hasStatus(200));
384 |
385 | request = new HttpPost("http://localhost/login");
386 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
387 | new BasicNameValuePair("username", "John"),
388 | new BasicNameValuePair("password", "wrong")
389 | )));
390 | response = httpClientMock.execute(request);
391 | assertThat(response, hasStatus(404));
392 | }
393 |
394 | @Test
395 | public void withFormParameter_should_match_when_allParametersHaveMatchingValue() throws IOException {
396 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
397 |
398 | httpClientMock.onPost("/login")
399 | .withFormParameter("username", "John")
400 | .withFormParameter("password", Matchers.containsString("secret"))
401 | .doReturnStatus(200);
402 |
403 | HttpPost request = new HttpPost("http://localhost/login");
404 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
405 | new BasicNameValuePair("username", "John"),
406 | new BasicNameValuePair("password", "secret!")
407 | )));
408 | HttpResponse response = httpClientMock.execute(request);
409 | assertThat(response, hasStatus(200));
410 | }
411 |
412 | @Test
413 | public void withFormParameters_should_match_when_allParametersHaveMatchingValue() throws IOException {
414 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
415 |
416 | ParametersMatcher parameters = new ParametersMatcher();
417 | parameters.put("username", Matchers.equalTo("John"));
418 | parameters.put("password", Matchers.containsString("secret"));
419 |
420 | httpClientMock.onPost("/login")
421 | .withFormParameters(parameters)
422 | .doReturnStatus(200);
423 |
424 | HttpPost request = new HttpPost("http://localhost/login");
425 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
426 | new BasicNameValuePair("username", "John"),
427 | new BasicNameValuePair("password", "secret!")
428 | )));
429 | HttpResponse response = httpClientMock.execute(request);
430 | assertThat(response, hasStatus(200));
431 |
432 | httpClientMock.debugOn();
433 | request = new HttpPost("http://localhost/login");
434 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
435 | new BasicNameValuePair("username", "John"),
436 | new BasicNameValuePair("password", "wrong")
437 | )));
438 | response = httpClientMock.execute(request);
439 | assertThat(response, hasStatus(404));
440 | }
441 |
442 | @Test
443 | public void withFormParameters_should_notMatch_when_formParameterHasNotMatchingValue() throws IOException {
444 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
445 | httpClientMock.onPost("/login")
446 | .withFormParameter("username", "John")
447 | .withFormParameter("password", "secret")
448 | .doReturnStatus(200);
449 |
450 | HttpPost request = new HttpPost("http://localhost/login");
451 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
452 | new BasicNameValuePair("username", "John"),
453 | new BasicNameValuePair("password", "wrong")
454 | )));
455 | HttpResponse response = httpClientMock.execute(request);
456 | assertThat(response, hasStatus(404));
457 | }
458 |
459 | @Test
460 | public void withFormParameter_should_notMatch_when_formParameterIsMissing() throws IOException {
461 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
462 | httpClientMock.onPost("/login")
463 | .withFormParameter("username", "John")
464 | .withFormParameter("password", "secret")
465 | .doReturnStatus(200);
466 |
467 | HttpPost request = new HttpPost("http://localhost/login");
468 | request.setEntity(new UrlEncodedFormEntity(Collections.singleton(
469 | new BasicNameValuePair("username", "John")
470 | )));
471 | HttpResponse response = httpClientMock.execute(request);
472 | assertThat(response, hasStatus(404));
473 | }
474 |
475 | @Test
476 | public void withFormParameter_should_notMatch_when_extraParameterIsPresent() throws IOException {
477 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
478 | httpClientMock.debugOn();
479 | httpClientMock.onPost("/login")
480 | .withFormParameter("username", "John")
481 | .withFormParameter("password", "secret")
482 | .withoutExtraFormParameters()
483 | .doReturnStatus(200);
484 |
485 | HttpPost request = new HttpPost("http://localhost/login");
486 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
487 | new BasicNameValuePair("username", "John"),
488 | new BasicNameValuePair("password", "secret"),
489 | new BasicNameValuePair("extra", "foo")
490 | )));
491 | HttpResponse response = httpClientMock.execute(request);
492 | assertThat(response, hasStatus(404));
493 | }
494 |
495 | @Test
496 | public void withFormParameter_should_Match_when_extraParameterIsPresentAndAllowExtraParametersIsTrue() throws IOException {
497 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
498 | httpClientMock.debugOn();
499 | httpClientMock.onPost("/login")
500 | .withFormParameter("username", "John")
501 | .withFormParameter("password", "secret")
502 | .withExtraFormParameters()
503 | .doReturnStatus(200);
504 |
505 | HttpPost request = new HttpPost("http://localhost/login");
506 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
507 | new BasicNameValuePair("username", "John"),
508 | new BasicNameValuePair("password", "secret"),
509 | new BasicNameValuePair("wrong", "bad")
510 | )));
511 | HttpResponse response = httpClientMock.execute(request);
512 | assertThat(response, hasStatus(200));
513 | }
514 |
515 | @Test
516 | public void should_notmatch_whenRequestHasExtraParametersAndOnPostWithoutUri() throws IOException {
517 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
518 |
519 | httpClientMock.onPost()
520 | .withPath("/login")
521 | .withoutExtraParameters()
522 | .doReturnStatus(200);
523 |
524 | HttpResponse response = httpClientMock.execute(new HttpPost("http://localhost/login?foo=bar"));
525 | assertThat(response, hasStatus(404));
526 | }
527 |
528 | @Test
529 | public void should_notMatch_whenRequestHasExtraParametersAndOnPostWithUri() throws IOException {
530 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
531 | httpClientMock.onPost("/login")
532 | .withoutExtraParameters()
533 | .doReturnStatus(200);
534 |
535 | HttpResponse response = httpClientMock.execute(new HttpPost("http://localhost/login?foo=bar"));
536 | assertThat(response, hasStatus(404));
537 | }
538 |
539 | @Test
540 | public void should_match_whenRequestHasExtraParametersAndAllowExtraParametersIsTrue() throws IOException {
541 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
542 |
543 | httpClientMock.onPost("/login")
544 | .withExtraParameters()
545 | .doReturnStatus(200);
546 |
547 | HttpResponse response = httpClientMock.execute(new HttpPost("http://localhost/login?foo=bar"));
548 | assertThat(response, hasStatus(200));
549 | }
550 |
551 | @Test
552 | public void should_notMatch_whenRequestHasExtraParametersAndAllowExtraParametersIsFalse() throws IOException {
553 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
554 |
555 | httpClientMock.onPost()
556 | .withPath("/login")
557 | .withoutExtraParameters()
558 | .doReturnStatus(200);
559 |
560 | HttpResponse response = httpClientMock.execute(new HttpPost("http://localhost/login?foo=bar"));
561 | assertThat(response, hasStatus(404));
562 | }
563 |
564 | @Test
565 | public void should_notMatch_whenRequestHasExtraFormParametersAndAllowExtraFormParametersIsFalse() throws IOException {
566 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
567 |
568 | httpClientMock.onPost()
569 | .withPath("/login")
570 | .withoutExtraFormParameters()
571 | .doReturnStatus(200);
572 | httpClientMock.onPost("/login")
573 | .withoutExtraFormParameters()
574 | .doReturnStatus(200);
575 |
576 | HttpPost request = new HttpPost("http://localhost/login");
577 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
578 | new BasicNameValuePair("username", "John")
579 | )));
580 | HttpResponse response = httpClientMock.execute(request);
581 | assertThat(response, hasStatus(404));
582 | }
583 |
584 | @Test
585 | public void should_work_with_non_absolute_uri() throws IOException {
586 | HttpClientMock httpClientMock = new HttpClientMock();
587 | httpClientMock.onGet().doReturn("ok");
588 | httpClientMock.onGet().withPath("/foo").doReturn("foo");
589 | HttpResponse ok = httpClientMock.execute(new HttpHost("localhost"), new HttpGet("/"));
590 | HttpResponse foo = httpClientMock.execute(new HttpHost("localhost"), new HttpGet("/foo"));
591 | assertThat(ok, hasContent("ok"));
592 | assertThat(foo, hasContent("foo"));
593 | }
594 |
595 | }
596 |
597 |
598 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/HttpClientMockBuilder_doReturnStatusTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static com.github.paweladamski.httpclientmock.Requests.httpGet;
4 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasContent;
5 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasStatus;
6 | import static org.hamcrest.MatcherAssert.assertThat;
7 |
8 | import java.io.IOException;
9 | import org.apache.http.client.methods.CloseableHttpResponse;
10 | import org.junit.jupiter.params.ParameterizedTest;
11 | import org.junit.jupiter.params.provider.ValueSource;
12 |
13 | public class HttpClientMockBuilder_doReturnStatusTest {
14 |
15 | @ParameterizedTest
16 | @ValueSource(ints = {200, 300, 400, 500})
17 | public void doReturnStatus_should_set_response_status_and_empty_entity(int statusCode) throws IOException {
18 | HttpClientMock httpClientMock = new HttpClientMock();
19 | httpClientMock.onGet().doReturnStatus(statusCode);
20 |
21 | CloseableHttpResponse response = httpClientMock.execute(httpGet("http://localhost"));
22 | assertThat(response, hasStatus(statusCode));
23 | assertThat(response, hasContent(""));
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/HttpClientMockBuilder_doReturnWithStatusTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static com.github.paweladamski.httpclientmock.Requests.httpGet;
4 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasNoEntity;
5 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasStatus;
6 | import static org.hamcrest.MatcherAssert.assertThat;
7 | import static org.hamcrest.Matchers.equalTo;
8 |
9 | import java.io.IOException;
10 | import org.apache.http.HttpResponse;
11 | import org.apache.http.client.methods.CloseableHttpResponse;
12 | import org.junit.jupiter.params.ParameterizedTest;
13 | import org.junit.jupiter.params.provider.ValueSource;
14 |
15 | public class HttpClientMockBuilder_doReturnWithStatusTest {
16 |
17 | @ParameterizedTest
18 | @ValueSource(ints = {200, 300, 400, 500})
19 | public void doReturn_should_set_response_status_empty_reason_and_null_entity_when_only_statusCode_is_provided(int statusCode) throws IOException {
20 | HttpClientMock httpClientMock = new HttpClientMock();
21 | httpClientMock.onGet().doReturnWithStatus(statusCode);
22 |
23 | CloseableHttpResponse response = httpClientMock.execute(httpGet("http://localhost"));
24 | assertThat(response, hasStatus(statusCode));
25 | assertThat(response, hasNoEntity());
26 | }
27 |
28 | @ParameterizedTest
29 | @ValueSource(ints = {200, 300, 400, 500})
30 | public void doReturn_should_set_response_status_and_reason_phrase(int statusCode) throws IOException {
31 | HttpClientMock httpClientMock = new HttpClientMock();
32 | httpClientMock.onGet().doReturnWithStatus(statusCode, "reason");
33 |
34 | HttpResponse response = httpClientMock.execute(httpGet("http://localhost"));
35 | assertThat(response, hasStatus(statusCode));
36 | assertThat(response.getStatusLine().getReasonPhrase(), equalTo("reason"));
37 | }
38 |
39 | }
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/HttpClientMockTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasStatus;
4 | import static org.hamcrest.MatcherAssert.assertThat;
5 | import static org.hamcrest.Matchers.equalTo;
6 |
7 | import java.io.IOException;
8 | import org.apache.http.HttpResponse;
9 | import org.apache.http.client.methods.HttpGet;
10 | import org.junit.jupiter.api.Test;
11 |
12 | public class HttpClientMockTest {
13 |
14 | @Test
15 | public void should_run_requestInterceptors() throws IOException {
16 | HttpClientMock httpClientMock = new HttpClientMock();
17 | httpClientMock.addRequestInterceptor((request, context) -> request.addHeader("foo", "bar"));
18 | httpClientMock.onGet().withHeader("foo", "bar").doReturn("ok");
19 |
20 | HttpResponse ok = httpClientMock.execute(new HttpGet("http://localhost"));
21 | assertThat(ok, hasStatus(200));
22 | }
23 |
24 | @Test
25 | public void should_run_responseInterceptors() throws IOException {
26 | HttpClientMock httpClientMock = new HttpClientMock();
27 | httpClientMock.addResponseInterceptor((request, context) -> request.addHeader("foo", "bar"));
28 | httpClientMock.onGet().doReturn("ok");
29 |
30 | HttpResponse ok = httpClientMock.execute(new HttpGet("http://localhost"));
31 | assertThat(ok.getFirstHeader("foo").getValue(), equalTo("bar"));
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/HttpClientResponseBuilderTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static com.github.paweladamski.httpclientmock.Asserts.assertThrows;
4 | import static com.github.paweladamski.httpclientmock.Requests.httpGet;
5 | import static com.github.paweladamski.httpclientmock.Requests.httpPost;
6 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasContent;
7 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasCookie;
8 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasReason;
9 | import static com.github.paweladamski.httpclientmock.matchers.HttpResponseMatchers.hasStatus;
10 | import static org.apache.http.HttpStatus.SC_NOT_FOUND;
11 | import static org.apache.http.HttpStatus.SC_NO_CONTENT;
12 | import static org.apache.http.entity.ContentType.APPLICATION_JSON;
13 | import static org.apache.http.entity.ContentType.APPLICATION_XML;
14 | import static org.hamcrest.MatcherAssert.assertThat;
15 | import static org.hamcrest.Matchers.equalTo;
16 | import static org.junit.jupiter.api.Assertions.assertEquals;
17 | import static org.junit.jupiter.api.Assertions.assertNull;
18 |
19 | import com.github.paweladamski.httpclientmock.action.Action;
20 | import java.io.IOException;
21 | import java.nio.charset.Charset;
22 | import java.nio.charset.StandardCharsets;
23 | import java.util.Arrays;
24 | import java.util.Collections;
25 | import java.util.List;
26 | import org.apache.http.HttpEntity;
27 | import org.apache.http.HttpResponse;
28 | import org.apache.http.NameValuePair;
29 | import org.apache.http.ProtocolVersion;
30 | import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
31 | import org.apache.http.client.methods.HttpGet;
32 | import org.apache.http.client.protocol.HttpClientContext;
33 | import org.apache.http.client.utils.URLEncodedUtils;
34 | import org.apache.http.entity.ContentType;
35 | import org.apache.http.message.BasicHttpResponse;
36 | import org.apache.http.message.BasicNameValuePair;
37 | import org.junit.jupiter.api.Assertions;
38 | import org.junit.jupiter.api.Test;
39 |
40 | public class HttpClientResponseBuilderTest {
41 |
42 | @Test
43 | public void should_return_status_404_when_no_rule_matches() throws IOException {
44 | HttpClientMock httpClientMock = new HttpClientMock();
45 | HttpResponse notFound = httpClientMock.execute(new HttpGet("http://localhost/foo"));
46 | assertThat(notFound, hasStatus(404));
47 | }
48 |
49 | @Test
50 | public void should_use_next_action_after_every_call() throws Exception {
51 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
52 |
53 | httpClientMock.onGet("/foo")
54 | .doReturn("first")
55 | .doReturn("second")
56 | .doReturn("third");
57 |
58 | httpClientMock.onGet("/bar")
59 | .doReturn("bar")
60 | .doReturnStatus(300)
61 | .doThrowException(new IOException());
62 |
63 | HttpResponse response1 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
64 | HttpResponse response2 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
65 | HttpResponse response3 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
66 | HttpResponse response4 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
67 | HttpResponse response5 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
68 |
69 | assertThat(response1, hasContent("first"));
70 | assertThat(response2, hasContent("second"));
71 | assertThat(response3, hasContent("third"));
72 | assertThat(response4, hasContent("third"));
73 | assertThat(response5, hasContent("third"));
74 |
75 | HttpResponse bar1 = httpClientMock.execute(new HttpGet("http://localhost/bar"));
76 | HttpResponse bar2 = httpClientMock.execute(new HttpGet("http://localhost/bar"));
77 | assertThat(bar1, hasContent("bar"));
78 | assertThat(bar2, hasStatus(300));
79 |
80 | assertThrows(IOException.class, () -> httpClientMock.execute(new HttpGet("http://localhost/bar")));
81 |
82 | }
83 |
84 | @Test
85 | public void should_support_response_in_different_charsets() throws IOException {
86 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
87 |
88 | httpClientMock.onGet("/foo")
89 | .doReturn("first")
90 | .doReturn("second", StandardCharsets.UTF_16)
91 | .doReturn("third", StandardCharsets.US_ASCII);
92 |
93 | HttpResponse response1 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
94 | HttpResponse response2 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
95 | HttpResponse response3 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
96 |
97 | assertThat(response1, hasContent("first", "UTF-8"));
98 | assertThat(response2, hasContent("second", "UTF-16"));
99 | assertThat(response3, hasContent("third", "ASCII"));
100 | }
101 |
102 | @Test
103 | public void should_support_response_with_different_contentType() throws IOException {
104 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
105 | httpClientMock
106 | .onGet("/json").doReturn("{\"a\":1}", Charset.defaultCharset(), APPLICATION_JSON);
107 | httpClientMock
108 | .onGet("/xml").doReturn("1", Charset.defaultCharset(), APPLICATION_XML);
109 |
110 | HttpResponse jsonResponse = httpClientMock.execute(httpGet("http://localhost:8080/json"));
111 | HttpResponse xmlResponse = httpClientMock.execute(httpGet("http://localhost:8080/xml"));
112 |
113 | assertThat(jsonResponse, hasContent("{\"a\":1}"));
114 | assertThat(jsonResponse.getFirstHeader("Content-type").getValue(), equalTo(APPLICATION_JSON.toString()));
115 | assertThat(ContentType.get(jsonResponse.getEntity()).toString(), equalTo(APPLICATION_JSON.toString()));
116 |
117 | assertThat(xmlResponse, hasContent("1"));
118 | assertThat(xmlResponse.getFirstHeader("Content-type").getValue(), equalTo(APPLICATION_XML.toString()));
119 | assertThat(ContentType.get(xmlResponse.getEntity()).toString(), equalTo(APPLICATION_XML.toString()));
120 |
121 | }
122 |
123 | @Test
124 | public void should_support_response_in_body_with_status() throws IOException {
125 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
126 |
127 | httpClientMock.onGet("/foo")
128 | .doReturn("first")
129 | .doReturn(300, "second")
130 | .doReturn(400, "third");
131 |
132 | HttpResponse response1 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
133 | HttpResponse response2 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
134 | HttpResponse response3 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
135 | HttpResponse response4 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
136 | HttpResponse response5 = httpClientMock.execute(new HttpGet("http://localhost/foo"));
137 |
138 | assertThat(response1, hasContent("first"));
139 | assertThat(response1, hasStatus(200));
140 | assertThat(response2, hasContent("second"));
141 | assertThat(response2, hasStatus(300));
142 | assertThat(response3, hasContent("third"));
143 | assertThat(response3, hasStatus(400));
144 | assertThat(response4, hasContent("third"));
145 | assertThat(response4, hasStatus(400));
146 | assertThat(response5, hasContent("third"));
147 | assertThat(response5, hasStatus(400));
148 | }
149 |
150 | @Test
151 | public void should_throw_exception_when_throwing_action_matched() throws IOException {
152 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
153 | httpClientMock.onGet("/foo").doThrowException(new IOException());
154 | Assertions.assertThrows(
155 | IOException.class,
156 | ()-> httpClientMock.execute(new HttpGet("http://localhost:8080/foo"))
157 | );
158 | }
159 |
160 | @Test
161 | public void should_return_status_corresponding_to_match() throws IOException {
162 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
163 |
164 | httpClientMock.onGet("/login").doReturnStatus(200);
165 | httpClientMock.onGet("/abc").doReturnStatus(404);
166 | httpClientMock.onGet("/error").doReturnStatus(500);
167 |
168 | HttpResponse ok = httpClientMock.execute(new HttpGet("http://localhost:8080/login"));
169 | HttpResponse notFound = httpClientMock.execute(new HttpGet("http://localhost:8080/abc"));
170 | HttpResponse error = httpClientMock.execute(new HttpGet("http://localhost:8080/error"));
171 |
172 | assertThat(ok, hasStatus(200));
173 | assertThat(notFound, hasStatus(404));
174 | assertThat(error, hasStatus(500));
175 |
176 | }
177 |
178 | @Test
179 | public void should_do_custom_action() throws IOException {
180 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
181 | httpClientMock.onPost("/login").doAction(echo());
182 | HttpResponse response = httpClientMock.execute(httpPost("http://localhost:8080/login", "foo bar"));
183 |
184 | assertThat(response, hasContent("foo bar"));
185 |
186 | }
187 |
188 | @Test
189 | public void should_add_header_to_response() throws IOException {
190 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
191 | httpClientMock.onPost("/login")
192 | .doReturn("foo").withHeader("tracking", "123")
193 | .doReturn("foo").withHeader("tracking", "456");
194 |
195 | HttpResponse first = httpClientMock.execute(httpPost("http://localhost:8080/login"));
196 | HttpResponse second = httpClientMock.execute(httpPost("http://localhost:8080/login"));
197 |
198 | assertThat(first.getFirstHeader("tracking").getValue(), equalTo("123"));
199 | assertThat(second.getFirstHeader("tracking").getValue(), equalTo("456"));
200 | }
201 |
202 | @Test
203 | public void should_add_cookie_to_context() throws IOException {
204 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
205 | httpClientMock.onPost("/login")
206 | .doReturn("foo").withCookie("cookieName", "cookieValue")
207 | .doReturn("foo").withCookie("cookieName", "cookieValue2");
208 |
209 | HttpClientContext httpClientContext = new HttpClientContext();
210 | httpClientMock.execute(httpPost("http://localhost:8080/login"), httpClientContext);
211 | assertThat(httpClientContext, hasCookie("cookieName", "cookieValue"));
212 |
213 | httpClientMock.execute(httpPost("http://localhost:8080/login"), httpClientContext);
214 | assertThat(httpClientContext, hasCookie("cookieName", "cookieValue2"));
215 | }
216 |
217 | @Test
218 | public void should_add_status_to_response() throws IOException {
219 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
220 | httpClientMock.onGet("/login")
221 | .doReturn("foo").withStatus(300);
222 | HttpResponse login = httpClientMock.execute(httpGet("http://localhost:8080/login"));
223 |
224 | assertThat(login, hasContent("foo"));
225 | assertThat(login, hasStatus(300));
226 |
227 | }
228 |
229 | @Test
230 | public void should_add_status_and_reason_to_response() throws IOException {
231 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
232 | httpClientMock.onGet("/login")
233 | .doReturn("foo").withStatus(400, "Bad request");
234 | HttpResponse login = httpClientMock.execute(httpGet("http://localhost:8080/login"));
235 |
236 | assertThat(login, hasContent("foo"));
237 | assertThat(login, hasStatus(400));
238 | assertThat(login, hasReason("Bad request"));
239 | }
240 |
241 | @Test
242 | public void should_return_json_with_right_header() throws IOException {
243 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
244 | httpClientMock.onGet("/login")
245 | .doReturnJSON("{foo:1}", StandardCharsets.UTF_8);
246 | HttpResponse login = httpClientMock.execute(httpGet("http://localhost:8080/login"));
247 |
248 | assertThat(login, hasContent("{foo:1}"));
249 | assertThat(login.getFirstHeader("Content-type").getValue(), equalTo(APPLICATION_JSON.toString()));
250 | }
251 |
252 | @Test
253 | public void should_return_json_with_right_content_type() throws IOException {
254 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
255 | httpClientMock.onGet("/login")
256 | .doReturnJSON("{foo:1}", StandardCharsets.UTF_8);
257 | HttpResponse login = httpClientMock.execute(httpGet("http://localhost:8080/login"));
258 |
259 | assertThat(login, hasContent("{foo:1}"));
260 | assertThat(ContentType.get(login.getEntity()).toString(), equalTo(APPLICATION_JSON.toString()));
261 | }
262 |
263 | @Test
264 | public void should_return_xml_with_right_header() throws IOException {
265 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
266 | httpClientMock.onGet("/login")
267 | .doReturnXML("bar", StandardCharsets.UTF_8);
268 | HttpResponse login = httpClientMock.execute(httpGet("http://localhost:8080/login"));
269 |
270 | assertThat(login, hasContent("bar"));
271 | assertThat(login.getFirstHeader("Content-type").getValue(), equalTo(APPLICATION_XML.toString()));
272 | }
273 |
274 | @Test
275 | public void should_return_xml_with_right_content_type() throws IOException {
276 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
277 | httpClientMock.onGet("/login")
278 | .doReturnXML("bar", StandardCharsets.UTF_8);
279 | HttpResponse login = httpClientMock.execute(httpGet("http://localhost:8080/login"));
280 |
281 | assertThat(login, hasContent("bar"));
282 | assertThat(ContentType.get(login.getEntity()).toString(), equalTo(APPLICATION_XML.toString()));
283 | }
284 |
285 | @Test
286 | public void should_not_set_response_entity_when_status_is_no_content() throws IOException {
287 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
288 | httpClientMock.onGet("/login")
289 | .doReturnStatus(SC_NO_CONTENT);
290 |
291 | HttpResponse login = httpClientMock.execute(httpGet("http://localhost:8080/login"));
292 |
293 | assertNull(login.getEntity());
294 | }
295 |
296 | @Test
297 | public void should_not_throw_exception_when_body_matcher_is_present_on_post_request() throws IOException {
298 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
299 | httpClientMock.onPost("/path1")
300 | .withBody(equalTo("Body content"))
301 | .doReturnStatus(200);
302 |
303 | HttpResponse response = httpClientMock.execute(httpGet("http://localhost:8080/path2"));
304 | assertThat(response, hasStatus(SC_NOT_FOUND));
305 | }
306 |
307 | @Test
308 | public void doReturnFormParams_should_returnResponseEntityWithFormParameters() throws IOException {
309 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
310 |
311 | List expected = Arrays.asList(
312 | new BasicNameValuePair("one", "1"),
313 | new BasicNameValuePair("two", "2")
314 | );
315 | httpClientMock.onGet("/path1").doReturnFormParams(expected);
316 |
317 | HttpResponse response = httpClientMock.execute(httpGet("http://localhost:8080/path1"));
318 | List actual = URLEncodedUtils.parse(response.getEntity());
319 |
320 | assertThat(response, hasStatus(200));
321 | assertEquals(expected, actual);
322 | }
323 |
324 | @Test
325 | public void doReturnFormParams_empty() throws IOException {
326 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
327 |
328 | List expected = Collections.emptyList();
329 | httpClientMock.onGet("/path1").doReturnFormParams(expected);
330 |
331 | HttpResponse response = httpClientMock.execute(httpGet("http://localhost:8080/path1"));
332 | List actual = URLEncodedUtils.parse(response.getEntity());
333 |
334 | assertThat(response, hasStatus(200));
335 | assertEquals(expected, actual);
336 | }
337 |
338 | private Action echo() {
339 | return r -> {
340 | HttpEntity entity = ((HttpEntityEnclosingRequestBase) r.getHttpRequest()).getEntity();
341 | BasicHttpResponse response = new BasicHttpResponse(new ProtocolVersion("http", 1, 1), 200, "ok");
342 | response.setEntity(entity);
343 | return response;
344 | };
345 | }
346 | }
347 |
348 |
349 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/HttpClientVerifyTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static com.github.paweladamski.httpclientmock.Requests.httpPost;
4 | import static com.github.paweladamski.httpclientmock.Requests.httpPut;
5 | import static org.hamcrest.Matchers.containsString;
6 | import static org.hamcrest.Matchers.greaterThanOrEqualTo;
7 |
8 | import com.github.paweladamski.httpclientmock.matchers.ParametersMatcher;
9 | import java.io.IOException;
10 | import java.util.Arrays;
11 | import org.apache.http.client.entity.UrlEncodedFormEntity;
12 | import org.apache.http.client.methods.HttpDelete;
13 | import org.apache.http.client.methods.HttpGet;
14 | import org.apache.http.client.methods.HttpHead;
15 | import org.apache.http.client.methods.HttpOptions;
16 | import org.apache.http.client.methods.HttpPatch;
17 | import org.apache.http.client.methods.HttpPost;
18 | import org.apache.http.client.methods.HttpPut;
19 | import org.apache.http.message.BasicNameValuePair;
20 | import org.hamcrest.Matchers;
21 | import org.junit.jupiter.api.Assertions;
22 | import org.junit.jupiter.api.Test;
23 |
24 | public class HttpClientVerifyTest {
25 |
26 | @Test
27 | public void shouldHandleAllHttpMethods() throws IOException {
28 |
29 | HttpClientMock httpClientMock = new HttpClientMock();
30 |
31 | httpClientMock.execute(new HttpGet("http://localhost"));
32 | httpClientMock.execute(new HttpPost("http://localhost"));
33 | httpClientMock.execute(new HttpDelete("http://localhost"));
34 | httpClientMock.execute(new HttpPut("http://localhost"));
35 | httpClientMock.execute(new HttpHead("http://localhost"));
36 | httpClientMock.execute(new HttpOptions("http://localhost"));
37 | httpClientMock.execute(new HttpPatch("http://localhost"));
38 |
39 | httpClientMock.verify()
40 | .get("http://localhost")
41 | .called();
42 | httpClientMock.verify()
43 | .post("http://localhost")
44 | .called();
45 | httpClientMock.verify()
46 | .delete("http://localhost")
47 | .called();
48 | httpClientMock.verify()
49 | .put("http://localhost")
50 | .called();
51 | httpClientMock.verify()
52 | .options("http://localhost")
53 | .called();
54 | httpClientMock.verify()
55 | .head("http://localhost")
56 | .called();
57 | httpClientMock.verify()
58 | .patch("http://localhost")
59 | .called();
60 | }
61 |
62 | @Test
63 | public void shouldCountNumberOfHttpMethodCalls() throws IOException {
64 | HttpClientMock httpClientMock = new HttpClientMock();
65 |
66 | httpClientMock.execute(new HttpGet("http://localhost"));
67 |
68 | httpClientMock.execute(new HttpPost("http://localhost"));
69 | httpClientMock.execute(new HttpPost("http://localhost"));
70 |
71 | httpClientMock.execute(new HttpDelete("http://localhost"));
72 | httpClientMock.execute(new HttpDelete("http://localhost"));
73 | httpClientMock.execute(new HttpDelete("http://localhost"));
74 |
75 | httpClientMock.verify()
76 | .get("http://localhost")
77 | .called();
78 | httpClientMock.verify()
79 | .post("http://localhost")
80 | .called(2);
81 | httpClientMock.verify()
82 | .delete("http://localhost")
83 | .called(3);
84 |
85 | httpClientMock.verify().get().called(greaterThanOrEqualTo(1));
86 | httpClientMock.verify().post().called(greaterThanOrEqualTo(1));
87 | httpClientMock.verify().delete().called(greaterThanOrEqualTo(1));
88 | }
89 |
90 | @Test
91 | public void shouldCountNumberOfUrlCalls() throws IOException {
92 | HttpClientMock httpClientMock = new HttpClientMock();
93 |
94 | httpClientMock.execute(new HttpGet("http://localhost"));
95 |
96 | httpClientMock.execute(new HttpGet("http://www.google.com"));
97 | httpClientMock.execute(new HttpGet("http://www.google.com"));
98 |
99 | httpClientMock.execute(new HttpGet("http://example.com"));
100 | httpClientMock.execute(new HttpGet("http://example.com"));
101 | httpClientMock.execute(new HttpGet("http://example.com"));
102 |
103 | httpClientMock.verify()
104 | .get("http://localhost")
105 | .called();
106 | httpClientMock.verify()
107 | .get("http://www.google.com")
108 | .called(2);
109 | httpClientMock.verify()
110 | .get("http://example.com")
111 | .called(3);
112 | }
113 |
114 | @Test
115 | public void shouldVerifyBodyContent() throws IOException {
116 | HttpClientMock httpClientMock = new HttpClientMock();
117 |
118 | httpClientMock.execute(httpPost("http://localhost", "foo"));
119 | httpClientMock.execute(httpPost("http://localhost", "foo"));
120 |
121 | httpClientMock.execute(httpPut("http://localhost", "bar"));
122 | httpClientMock.execute(httpPut("http://localhost", "foo"));
123 |
124 | httpClientMock.verify()
125 | .post("http://localhost")
126 | .withBody(containsString("foo"))
127 | .called(2);
128 | httpClientMock.verify()
129 | .put("http://localhost")
130 | .withBody(containsString("bar"))
131 | .called();
132 | httpClientMock.verify()
133 | .get("http://localhost")
134 | .withBody(containsString("foo bar"))
135 | .notCalled();
136 | }
137 |
138 | @Test
139 | public void should_handle_path_with_query_parameter() throws IOException {
140 | HttpClientMock httpClientMock = new HttpClientMock();
141 |
142 | httpClientMock.execute(httpPost("http://localhost?a=1&b=2&c=3"));
143 | httpClientMock.execute(httpPost("http://localhost?a=1&b=2"));
144 | httpClientMock.execute(httpPost("http://localhost?a=1"));
145 |
146 | httpClientMock.verify()
147 | .post("http://localhost?d=3")
148 | .notCalled();
149 | httpClientMock.verify()
150 | .post("http://localhost?a=3")
151 | .notCalled();
152 | httpClientMock.verify()
153 | .post("http://localhost?a=1&b=2&c=3")
154 | .called(1);
155 | httpClientMock.verify()
156 | .post("http://localhost?a=1&b=2")
157 | .called(2);
158 | httpClientMock.verify()
159 | .post("http://localhost?a=1")
160 | .called(3);
161 | httpClientMock.verify()
162 | .post("http://localhost")
163 | .withParameter("a", "1")
164 | .called(3);
165 |
166 | httpClientMock.verify()
167 | .post("http://localhost")
168 | .withExtraParameters()
169 | .called(3);
170 | httpClientMock.verify()
171 | .post("http://localhost")
172 | .withoutExtraParameters()
173 | .notCalled();
174 | }
175 |
176 | @Test
177 | public void should_handle_path_with_reference() throws IOException {
178 | HttpClientMock httpClientMock = new HttpClientMock();
179 |
180 | httpClientMock.execute(httpPost("http://localhost?a=1#abc"));
181 | httpClientMock.execute(httpPost("http://localhost#xyz"));
182 |
183 | httpClientMock.verify()
184 | .post("http://localhost?a=1#abc")
185 | .called(1);
186 | httpClientMock.verify()
187 | .post("http://localhost#abc")
188 | .withoutExtraParameters()
189 | .notCalled();
190 | httpClientMock.verify()
191 | .post("http://localhost#xyz")
192 | .called(1);
193 | httpClientMock.verify()
194 | .post("http://localhost")
195 | .notCalled();
196 | }
197 |
198 | @Test
199 | public void should_throw_exception_when_number_of_calls_is_wrong() throws IOException {
200 | HttpClientMock httpClientMock = new HttpClientMock();
201 |
202 | httpClientMock.execute(httpPost("http://localhost?a=1"));
203 |
204 | Assertions.assertThrows(
205 | Exception.class,
206 | () -> httpClientMock.verify().post("http://localhost?a=1#abc").called(2)
207 | );
208 | }
209 |
210 | @Test
211 | public void should_allow_different_host_then_default() throws IOException {
212 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
213 |
214 | httpClientMock.onGet("/login").doReturn("login");
215 | httpClientMock.onGet("http://www.google.com").doReturn("google");
216 |
217 | httpClientMock.execute(new HttpGet("http://localhost/login"));
218 | httpClientMock.execute(new HttpGet("http://www.google.com"));
219 |
220 | httpClientMock.verify().get("/login").called();
221 | httpClientMock.verify().get("http://www.google.com").called();
222 | }
223 |
224 | @Test
225 | public void should_check_header() throws IOException {
226 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost:8080");
227 |
228 | httpClientMock.onGet("/login").doReturn("OK");
229 |
230 | HttpGet getMozilla = new HttpGet("http://localhost:8080/login");
231 | HttpGet getChrome = new HttpGet("http://localhost:8080/login");
232 | getMozilla.addHeader("User-Agent", "Mozilla");
233 | getChrome.addHeader("User-Agent", "Chrome");
234 | httpClientMock.execute(getChrome);
235 | httpClientMock.execute(getMozilla);
236 |
237 | httpClientMock.verify().get("/login").withHeader("User-Agent", "Mozilla").called();
238 | httpClientMock.verify().get("/login").withHeader("User-Agent", "Chrome").called();
239 | httpClientMock.verify().get("/login").withHeader("User-Agent", "IE").notCalled();
240 | }
241 |
242 | @Test
243 | public void withFormParameter_should_match_when_allParametersHaveMatchingValue() throws IOException {
244 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
245 |
246 | HttpPost request = new HttpPost("http://localhost/login");
247 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
248 | new BasicNameValuePair("username", "John"),
249 | new BasicNameValuePair("password", "secret!")
250 | )));
251 | httpClientMock.execute(request);
252 |
253 | httpClientMock.verify()
254 | .post("/login")
255 | .withFormParameter("username", "John")
256 | .withFormParameter("password", Matchers.containsString("secret"))
257 | .called();
258 | }
259 |
260 | @Test
261 | public void withFormParameter_should_notMatch_when_parameterHaveNotMatchingValue() throws IOException {
262 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
263 |
264 | HttpPost request = new HttpPost("http://localhost/login");
265 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
266 | new BasicNameValuePair("username", "John"),
267 | new BasicNameValuePair("password", "secret!")
268 | )));
269 | httpClientMock.execute(request);
270 |
271 | httpClientMock.verify()
272 | .post("/login")
273 | .withFormParameter("username", "John")
274 | .withFormParameter("password", Matchers.containsString("abc"))
275 | .notCalled();
276 | }
277 |
278 | @Test
279 | public void withFormParameters_should_match_when_allParametersHaveMatchingValue() throws IOException {
280 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
281 |
282 | HttpPost request = new HttpPost("http://localhost/login");
283 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
284 | new BasicNameValuePair("username", "John"),
285 | new BasicNameValuePair("password", "secret!")
286 | )));
287 | httpClientMock.execute(request);
288 |
289 | ParametersMatcher parameters = new ParametersMatcher();
290 | parameters.put("username", Matchers.equalTo("John"));
291 | parameters.put("password", Matchers.containsString("secret"));
292 | httpClientMock.verify().post("/login")
293 | .withFormParameters(parameters)
294 | .called();
295 | }
296 |
297 | @Test
298 | public void withFormParameters_should_match_when_requestHasExtraParametersAndAllowExtraParametersIsTrue() throws IOException {
299 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
300 |
301 | HttpPost request = new HttpPost("http://localhost/login");
302 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
303 | new BasicNameValuePair("username", "John"),
304 | new BasicNameValuePair("password", "secret!")
305 | )));
306 | httpClientMock.execute(request);
307 |
308 | ParametersMatcher parameters = new ParametersMatcher();
309 | parameters.put("username", Matchers.equalTo("John"));
310 |
311 | httpClientMock.verify().post("/login")
312 | .withFormParameters(parameters)
313 | .withExtraFormParameters()
314 | .called();
315 | }
316 |
317 | @Test
318 | public void withFormParameters_should_notMatch_when_requestHasExtraParametersAndAllowExtraFormParametersIsFalse() throws IOException {
319 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
320 |
321 | HttpPost request = new HttpPost("http://localhost/login");
322 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
323 | new BasicNameValuePair("username", "John"),
324 | new BasicNameValuePair("password", "secret!")
325 | )));
326 | httpClientMock.execute(request);
327 |
328 | ParametersMatcher parameters = new ParametersMatcher();
329 | parameters.put("username", Matchers.equalTo("John"));
330 |
331 | httpClientMock.verify().post().withPath("/login")
332 | .withFormParameters(parameters)
333 | .withoutExtraFormParameters()
334 | .notCalled();
335 | }
336 |
337 | @Test
338 | public void withFormParameters_when_requestHasExtraFormParameters() throws IOException {
339 | HttpClientMock httpClientMock = new HttpClientMock("http://localhost");
340 |
341 | HttpPost request = new HttpPost("http://localhost/login");
342 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
343 | new BasicNameValuePair("username", "John"),
344 | new BasicNameValuePair("password", "secret!")
345 | )));
346 | httpClientMock.execute(request);
347 |
348 | ParametersMatcher parameters = new ParametersMatcher();
349 | parameters.put("username", Matchers.equalTo("John"));
350 |
351 | httpClientMock.verify().post("/login")
352 | .withFormParameters(parameters)
353 | .withoutExtraFormParameters()
354 | .notCalled();
355 | httpClientMock.verify().post("/login")
356 | .withFormParameters(parameters)
357 | .withExtraFormParameters()
358 | .called();
359 | }
360 |
361 | }
362 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/Requests.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import java.io.UnsupportedEncodingException;
4 | import org.apache.http.HttpEntity;
5 | import org.apache.http.client.methods.HttpGet;
6 | import org.apache.http.client.methods.HttpPost;
7 | import org.apache.http.client.methods.HttpPut;
8 | import org.apache.http.client.methods.HttpUriRequest;
9 | import org.apache.http.entity.StringEntity;
10 |
11 | class Requests {
12 |
13 | public static HttpUriRequest httpGet(String host) {
14 | return new HttpGet(host);
15 | }
16 |
17 | public static HttpUriRequest httpPost(String host) throws UnsupportedEncodingException {
18 | return httpPost(host, "");
19 | }
20 |
21 | public static HttpUriRequest httpPost(String host, String content) throws UnsupportedEncodingException {
22 | HttpPost post = new HttpPost(host);
23 | HttpEntity entity = new StringEntity(content);
24 | post.setEntity(entity);
25 | return post;
26 | }
27 |
28 | public static HttpUriRequest httpPut(String host, String content) throws UnsupportedEncodingException {
29 | HttpPut post = new HttpPut(host);
30 | HttpEntity entity = new StringEntity(content);
31 | post.setEntity(entity);
32 | return post;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/ThrowingRunnable.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | @FunctionalInterface
4 | interface ThrowingRunnable {
5 |
6 | void run() throws Exception;
7 | }
8 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/UrlParamsParserTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import java.util.List;
6 | import org.apache.http.NameValuePair;
7 | import org.junit.jupiter.api.Test;
8 |
9 | public class UrlParamsParserTest {
10 |
11 | @Test
12 | public void shouldParseQueryString() {
13 | List params = new UrlParamsParser().parse("a=1&b=2");
14 | assertEquals("a", params.get(0).getName());
15 | assertEquals("1", params.get(0).getValue());
16 | assertEquals("b", params.get(1).getName());
17 | assertEquals("2", params.get(1).getValue());
18 | }
19 |
20 | @Test
21 | public void shouldReturnEmptyListForNull() {
22 | assertEquals(0, new UrlParamsParser().parse(null).size());
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/UrlParserTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock;
2 |
3 | import static com.github.paweladamski.httpclientmock.UrlParser.EMPTY_PORT_NUMBER;
4 | import static org.junit.jupiter.api.Assertions.assertTrue;
5 |
6 | import org.junit.jupiter.api.BeforeEach;
7 | import org.junit.jupiter.api.Test;
8 |
9 | public class UrlParserTest {
10 |
11 | private UrlParser urlParser;
12 |
13 | @BeforeEach
14 | public void setUp() {
15 | urlParser = new UrlParser();
16 | }
17 |
18 | @Test
19 | public void parseHost() {
20 | UrlConditions urlConditions = urlParser.parse("http://localhost");
21 | assertTrue(urlConditions.getHostConditions().get(0).matches("localhost"));
22 | assertTrue(urlConditions.getPortConditions().get(0).matches(EMPTY_PORT_NUMBER));
23 | assertTrue(urlConditions.getReferenceConditions().matches(""));
24 | }
25 |
26 | @Test
27 | public void parseHostWithPort() {
28 | UrlConditions urlConditions = urlParser.parse("http://localhost:8080");
29 | assertTrue(urlConditions.getHostConditions().get(0).matches("localhost"));
30 | assertTrue(urlConditions.getPortConditions().get(0).matches(8080));
31 | }
32 |
33 | @Test
34 | public void parseHostAndPath() {
35 | UrlConditions urlConditions = urlParser.parse("http://localhost/foo/bar");
36 | assertTrue(urlConditions.getHostConditions().get(0).matches("localhost"));
37 | assertTrue(urlConditions.getPathConditions().get(0).matches("/foo/bar"));
38 | }
39 |
40 | @Test
41 | public void parseHostAndPathAndParameters() {
42 | UrlConditions urlConditions = urlParser.parse("http://localhost/foo/bar?a=1&b=2");
43 | assertTrue(urlConditions.getHostConditions().get(0).matches("localhost"));
44 | assertTrue(urlConditions.getPathConditions().get(0).matches("/foo/bar"));
45 | assertTrue(urlConditions.getUrlQueryConditions().matches("a=1&b=2"));
46 | }
47 |
48 | @Test
49 | public void parseHostReference() {
50 | UrlConditions urlConditions = urlParser.parse("http://localhost#abc");
51 | assertTrue(urlConditions.getHostConditions().get(0).matches("localhost"));
52 | assertTrue(urlConditions.getReferenceConditions().matches("abc"));
53 | }
54 |
55 | }
56 |
57 |
58 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/action/UrlEncodedFormEntityResponseTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.action;
2 |
3 | import static org.junit.jupiter.api.Assertions.assertEquals;
4 |
5 | import java.nio.charset.StandardCharsets;
6 | import java.util.Arrays;
7 | import java.util.List;
8 | import org.apache.http.HttpResponse;
9 | import org.apache.http.NameValuePair;
10 | import org.apache.http.client.utils.URLEncodedUtils;
11 | import org.apache.http.message.BasicNameValuePair;
12 | import org.junit.jupiter.api.Test;
13 |
14 | /**
15 | * @author Michael Angstadt
16 | */
17 | public class UrlEncodedFormEntityResponseTest {
18 |
19 | @Test
20 | public void test() throws Exception {
21 | List expectedPairs = Arrays.asList(new BasicNameValuePair("one", "1"), new BasicNameValuePair("two", "2"));
22 | int expectedStatus = 500;
23 |
24 | UrlEncodedFormEntityResponse action = new UrlEncodedFormEntityResponse(expectedStatus, expectedPairs, StandardCharsets.UTF_8);
25 | HttpResponse response = action.getResponse(null);
26 |
27 | List actualPairs = URLEncodedUtils.parse(response.getEntity());
28 | assertEquals(expectedPairs, actualPairs);
29 |
30 | assertEquals(expectedStatus, response.getStatusLine().getStatusCode());
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/condition/UrlEncodedFormConditionTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.condition;
2 |
3 | import static org.hamcrest.MatcherAssert.assertThat;
4 | import static org.hamcrest.Matchers.contains;
5 | import static org.hamcrest.Matchers.empty;
6 | import static org.hamcrest.Matchers.equalTo;
7 | import static org.junit.jupiter.api.Assertions.assertFalse;
8 | import static org.junit.jupiter.api.Assertions.assertTrue;
9 |
10 | import com.github.paweladamski.httpclientmock.Debugger;
11 | import com.github.paweladamski.httpclientmock.Request;
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.List;
15 | import org.apache.http.HttpEntity;
16 | import org.apache.http.client.entity.UrlEncodedFormEntity;
17 | import org.apache.http.client.methods.HttpGet;
18 | import org.apache.http.client.methods.HttpPost;
19 | import org.apache.http.client.utils.URLEncodedUtils;
20 | import org.apache.http.entity.StringEntity;
21 | import org.apache.http.message.BasicNameValuePair;
22 | import org.junit.jupiter.api.Test;
23 |
24 | /**
25 | * @author Michael Angstadt
26 | */
27 | public class UrlEncodedFormConditionTest {
28 |
29 | @Test
30 | public void valid_match() throws Exception {
31 | UrlEncodedFormCondition condition = new UrlEncodedFormCondition();
32 | condition.addExpectedParameter("one", equalTo("1"));
33 | condition.addExpectedParameter("two", equalTo("2"));
34 |
35 | HttpPost request = new HttpPost();
36 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
37 | new BasicNameValuePair("one", "1"),
38 | new BasicNameValuePair("two", "2")
39 | )));
40 |
41 | Request r = new Request(null, request, null);
42 | assertTrue(condition.matches(r));
43 |
44 | TestDebugger debugger = new TestDebugger();
45 | condition.debug(r, debugger);
46 | assertThat(debugger.matching, contains(
47 | "form parameter one is \"1\"",
48 | "form parameter two is \"2\""
49 | ));
50 | assertThat(debugger.notMatching, empty());
51 | }
52 |
53 | @Test
54 | public void case_sensitive_names() throws Exception {
55 | UrlEncodedFormCondition condition = new UrlEncodedFormCondition();
56 | condition.addExpectedParameter("ONE", equalTo("1"));
57 |
58 | HttpPost request = new HttpPost();
59 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
60 | new BasicNameValuePair("one", "1")
61 | )));
62 |
63 | Request r = new Request(null, request, null);
64 | assertFalse(condition.matches(r));
65 |
66 | TestDebugger debugger = new TestDebugger();
67 | condition.debug(r, debugger);
68 | assertThat(debugger.matching, empty());
69 | assertThat(debugger.notMatching, contains(
70 | "form parameter ONE is missing from the request",
71 | "form parameter one was not expected to be in the request"
72 | ));
73 | }
74 |
75 | @Test
76 | public void no_match() throws Exception {
77 | UrlEncodedFormCondition condition = new UrlEncodedFormCondition();
78 | condition.addExpectedParameter("one", equalTo("1"));
79 | condition.addExpectedParameter("two", equalTo("2"));
80 |
81 | HttpPost request = new HttpPost();
82 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
83 | new BasicNameValuePair("one", "1"),
84 | new BasicNameValuePair("two", "not 2")
85 | )));
86 |
87 | Request r = new Request(null, request, null);
88 | assertFalse(condition.matches(r));
89 |
90 | TestDebugger debugger = new TestDebugger();
91 | condition.debug(r, debugger);
92 | assertThat(debugger.matching, contains(
93 | "form parameter one is \"1\""
94 | ));
95 | assertThat(debugger.notMatching, contains(
96 | "form parameter two is \"2\""
97 | ));
98 | }
99 |
100 | /**
101 | * Parameters with the same name are not supported because there's no way of telling which Matcher to assign to which parameter.
102 | */
103 | @Test
104 | public void duplicate_names() throws Exception {
105 | UrlEncodedFormCondition condition = new UrlEncodedFormCondition();
106 | condition.addExpectedParameter("one", equalTo("1"));
107 | condition.addExpectedParameter("one", equalTo(
108 | "3")); //MatchersMap requires that the parameter value match BOTH conditions--so the value must equal "1" and must also equal "3", which is impossible
109 |
110 | HttpPost request = new HttpPost();
111 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
112 | new BasicNameValuePair("one", "1"),
113 | new BasicNameValuePair("one", "3")
114 | )));
115 |
116 | Request r = new Request(null, request, null);
117 | assertFalse(condition.matches(r));
118 |
119 | TestDebugger debugger = new TestDebugger();
120 | condition.debug(r, debugger);
121 | assertThat(debugger.matching, empty());
122 | assertThat(debugger.notMatching, contains(
123 | "form parameter one is \"1\" and \"3\"",
124 | "form parameter one is \"1\" and \"3\""
125 | ));
126 | }
127 |
128 | @Test
129 | public void different_number_of_parameters() throws Exception {
130 | UrlEncodedFormCondition condition = new UrlEncodedFormCondition();
131 | condition.addExpectedParameter("one", equalTo("1"));
132 |
133 | HttpPost request = new HttpPost();
134 | request.setEntity(new UrlEncodedFormEntity(Arrays.asList(
135 | new BasicNameValuePair("one", "1"),
136 | new BasicNameValuePair("two", "2")
137 | )));
138 |
139 | Request r = new Request(null, request, null);
140 | assertFalse(condition.matches(r));
141 |
142 | TestDebugger debugger = new TestDebugger();
143 | condition.debug(r, debugger);
144 | assertThat(debugger.matching, contains(
145 | "form parameter one is \"1\""
146 | ));
147 | assertThat(debugger.notMatching, contains(
148 | "form parameter two was not expected to be in the request"
149 | ));
150 | }
151 |
152 | /**
153 | * The method that is used to extract the form parameters out of the request body ({@link URLEncodedUtils#parse(HttpEntity)}) also takes the Content-Type of
154 | * the request into consideration. If the Content-Type is not "application/x-www-form-urlencoded", then it will not attempt to parse the body and it will act
155 | * as if the body has zero form parameters in it.
156 | */
157 | @Test
158 | public void body_contains_form_parameters_but_content_type_is_different() throws Exception {
159 | {
160 | UrlEncodedFormCondition condition = new UrlEncodedFormCondition();
161 |
162 | HttpPost request = new HttpPost();
163 | request.setEntity(new StringEntity("one=1"));
164 |
165 | Request r = new Request(null, request, null);
166 | assertTrue(condition.matches(r));
167 |
168 | TestDebugger debugger = new TestDebugger();
169 | condition.debug(r, debugger);
170 | assertThat(debugger.matching, empty());
171 | assertThat(debugger.notMatching, empty());
172 | }
173 |
174 | {
175 | UrlEncodedFormCondition condition = new UrlEncodedFormCondition();
176 | condition.addExpectedParameter("one", equalTo("1"));
177 |
178 | HttpPost request = new HttpPost();
179 | request.setEntity(new StringEntity("one=1"));
180 |
181 | Request r = new Request(null, request, null);
182 | assertFalse(condition.matches(r)); //request does not use "application/x-www-form-urlencoded" content type
183 |
184 | TestDebugger debugger = new TestDebugger();
185 | condition.debug(r, debugger);
186 | assertThat(debugger.matching, empty());
187 | assertThat(debugger.notMatching, contains(
188 | "form parameter one is missing from the request"
189 | ));
190 | }
191 | }
192 |
193 | @Test
194 | public void bodyless_request() {
195 | //without expected params
196 | {
197 | UrlEncodedFormCondition condition = new UrlEncodedFormCondition();
198 | HttpGet request = new HttpGet();
199 | Request r = new Request(null, request, null);
200 | assertTrue(condition.matches(r));
201 |
202 | TestDebugger debugger = new TestDebugger();
203 | condition.debug(r, debugger);
204 | assertThat(debugger.matching, empty());
205 | assertThat(debugger.notMatching, empty());
206 | }
207 |
208 | //with expected params
209 | {
210 | UrlEncodedFormCondition condition = new UrlEncodedFormCondition();
211 | condition.addExpectedParameter("foo", equalTo("bar"));
212 | HttpGet request = new HttpGet();
213 | Request r = new Request(null, request, null);
214 | assertFalse(condition.matches(r));
215 |
216 | TestDebugger debugger = new TestDebugger();
217 | condition.debug(r, debugger);
218 | assertThat(debugger.matching, empty());
219 | assertThat(debugger.notMatching, contains(
220 | "form parameter foo is missing from the request"
221 | ));
222 | }
223 | }
224 |
225 | private static class TestDebugger extends Debugger {
226 |
227 | public final List matching = new ArrayList<>();
228 | public final List notMatching = new ArrayList<>();
229 |
230 | @Override
231 | public void message(boolean matches, String message) {
232 | List list = matches ? matching : notMatching;
233 | list.add(message);
234 | }
235 | }
236 | }
237 |
--------------------------------------------------------------------------------
/src/test/java/com/github/paweladamski/httpclientmock/matchers/ParametersMatcherTest.java:
--------------------------------------------------------------------------------
1 | package com.github.paweladamski.httpclientmock.matchers;
2 |
3 | import static org.hamcrest.Matchers.equalTo;
4 | import static org.junit.jupiter.api.Assertions.assertFalse;
5 | import static org.junit.jupiter.api.Assertions.assertTrue;
6 |
7 | import java.util.ArrayList;
8 | import java.util.Collections;
9 | import org.apache.http.NameValuePair;
10 | import org.apache.http.message.BasicNameValuePair;
11 | import org.hamcrest.Matchers;
12 | import org.junit.jupiter.api.BeforeEach;
13 | import org.junit.jupiter.api.Test;
14 |
15 | public class ParametersMatcherTest {
16 |
17 | ParametersMatcher matcher;
18 | ArrayList actualParameters;
19 |
20 | @BeforeEach
21 | public void setUp() {
22 | matcher = new ParametersMatcher();
23 | actualParameters = new ArrayList<>();
24 | }
25 |
26 | @Test
27 | public void match_shouldReturnTrue_When_NoParamsWereExpectedAndNoParamsInActualList() {
28 | assertTrue(matcher.matches(Collections.EMPTY_LIST));
29 | }
30 |
31 | @Test
32 | public void matchesAndAllowExtraParameters_shouldReturnTrue_When_NoParamsWereExpectedAndNoParamsInActualList() {
33 | assertTrue(matcher.matchesAndAllowExtraParameters(Collections.EMPTY_LIST));
34 | }
35 |
36 | @Test
37 | public void match_shouldReturnTrue_When_OneParamIsExpectedAndTheSameParamsInActualList() {
38 | matcher.put("foo", equalTo("bar"));
39 | actualParameters.add(new BasicNameValuePair("foo", "bar"));
40 |
41 | assertTrue(matcher.matches(actualParameters));
42 | }
43 |
44 | @Test
45 | public void matchesAndAllowExtraParameters_shouldReturnTrue_When_OneParamIsExpectedAndTheSameParamsInActualList() {
46 | matcher.put("foo", equalTo("bar"));
47 | actualParameters.add(new BasicNameValuePair("foo", "bar"));
48 |
49 | assertTrue(matcher.matches(actualParameters));
50 | }
51 |
52 | @Test
53 | public void match_shouldReturnFalse_When_ActualParametersHaveOneExtraParameter() {
54 | matcher.put("foo", equalTo("bar"));
55 | actualParameters.add(new BasicNameValuePair("foo", "bar"));
56 | actualParameters.add(new BasicNameValuePair("abc", "123"));
57 |
58 | assertFalse(matcher.matches(actualParameters));
59 | }
60 |
61 | @Test
62 | public void matchesAndAllowExtraParameters_shouldReturnTrue_When_ActualParametersHaveOneExtraParameter() {
63 | matcher.put("foo", equalTo("bar"));
64 | actualParameters.add(new BasicNameValuePair("foo", "bar"));
65 | actualParameters.add(new BasicNameValuePair("abc", "123"));
66 |
67 | assertTrue(matcher.matchesAndAllowExtraParameters(actualParameters));
68 | }
69 |
70 | @Test
71 | public void match_shouldReturnFalse_When_ActualContainNotMatchingParameter() {
72 | matcher.put("foo", equalTo("bar"));
73 | actualParameters.add(new BasicNameValuePair("foo", "123"));
74 |
75 | assertFalse(matcher.matches(actualParameters));
76 | }
77 |
78 | @Test
79 | public void matchesAndAllowExtraParameters_shouldReturnFalse_When_ActualContainNotMatchingParameter() {
80 | matcher.put("foo", equalTo("bar"));
81 | actualParameters.add(new BasicNameValuePair("foo", "123"));
82 |
83 | assertFalse(matcher.matchesAndAllowExtraParameters(actualParameters));
84 | }
85 |
86 | @Test
87 | public void match_shouldReturnFalse_When_ActualMissesOneOfTheExpectedParameter() {
88 | matcher.put("foo", equalTo("bar"));
89 | matcher.put("abc", equalTo("123"));
90 | actualParameters.add(new BasicNameValuePair("foo", "bar"));
91 |
92 | assertFalse(matcher.matches(actualParameters));
93 | }
94 |
95 | @Test
96 | public void matchesAndAllowExtraParameters_shouldReturnFalse_When_ActualMissesOneOfTheExpectedParameter() {
97 | matcher.put("foo", equalTo("bar"));
98 | matcher.put("abc", equalTo("123"));
99 | actualParameters.add(new BasicNameValuePair("foo", "bar"));
100 |
101 | assertFalse(matcher.matchesAndAllowExtraParameters(actualParameters));
102 | }
103 |
104 | @Test
105 | public void put_should_addNewMatchers_when_addingMatcherForExistingParameter() {
106 | matcher.put("foo", Matchers.containsString("a"));
107 | matcher.put("foo", Matchers.containsString("b"));
108 |
109 | actualParameters.add(new BasicNameValuePair("foo", "a"));
110 | assertFalse(matcher.matches(actualParameters));
111 |
112 | actualParameters.clear();
113 | actualParameters.add(new BasicNameValuePair("foo", "b"));
114 | assertFalse(matcher.matches(actualParameters));
115 |
116 | actualParameters.clear();
117 | actualParameters.add(new BasicNameValuePair("foo", "bar"));
118 | assertTrue(matcher.matches(actualParameters));
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------