Skip to content

Commit ea537d7

Browse files
committed
Add unit tests for HttpOpener. (#463)
1 parent 864f0da commit ea537d7

File tree

2 files changed

+333
-0
lines changed

2 files changed

+333
-0
lines changed

metafacture-io/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ dependencies {
2323
implementation 'commons-io:commons-io:2.5'
2424
implementation 'org.apache.commons:commons-compress:1.21'
2525
runtimeOnly 'org.tukaani:xz:1.6'
26+
testImplementation 'com.github.tomakehurst:wiremock-jre8:2.33.2'
2627
testImplementation 'junit:junit:4.12'
2728
testImplementation 'org.mockito:mockito-core:2.5.5'
2829
testImplementation 'org.assertj:assertj-core:3.11.1'
30+
testRuntimeOnly 'org.slf4j:slf4j-simple:1.7.21'
2931
}
Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
/*
2+
* Copyright 2013, 2022 Deutsche Nationalbibliothek et al
3+
*
4+
* Licensed under the Apache License, Version 2.0 the "License";
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.metafacture.io;
18+
19+
import org.metafacture.commons.ResourceUtil;
20+
import org.metafacture.framework.ObjectReceiver;
21+
22+
import com.github.tomakehurst.wiremock.client.MappingBuilder;
23+
import com.github.tomakehurst.wiremock.client.ResponseDefinitionBuilder;
24+
import com.github.tomakehurst.wiremock.client.WireMock;
25+
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
26+
import com.github.tomakehurst.wiremock.http.RequestMethod;
27+
import com.github.tomakehurst.wiremock.junit.WireMockRule;
28+
import com.github.tomakehurst.wiremock.matching.RequestPatternBuilder;
29+
import com.github.tomakehurst.wiremock.matching.StringValuePattern;
30+
import com.github.tomakehurst.wiremock.matching.UrlPattern;
31+
import org.junit.Assert;
32+
import org.junit.ComparisonFailure;
33+
import org.junit.Rule;
34+
import org.junit.Test;
35+
import org.mockito.ArgumentCaptor;
36+
import org.mockito.Captor;
37+
import org.mockito.Mock;
38+
import org.mockito.Mockito;
39+
import org.mockito.junit.MockitoJUnit;
40+
import org.mockito.junit.MockitoRule;
41+
42+
import java.io.IOException;
43+
import java.io.Reader;
44+
import java.util.Arrays;
45+
import java.util.function.BiConsumer;
46+
import java.util.function.Consumer;
47+
48+
/**
49+
* Tests for class {@link HttpOpener}.
50+
*
51+
* @author Jens Wille
52+
*/
53+
public final class HttpOpenerTest {
54+
55+
private static final String TEST_PATH = "/test/path";
56+
private static final String TEST_URL = "%s" + TEST_PATH;
57+
58+
private static final String TEST_STRING = "test string";
59+
private static final StringValuePattern TEST_VALUE = WireMock.equalTo(TEST_STRING);
60+
61+
private static final String TEST_ERROR = "400 - Bad Request";
62+
63+
private static final String REQUEST_BODY = "request body";
64+
private static final String RESPONSE_BODY = "response bödy"; // UTF-8
65+
66+
@Rule
67+
public MockitoRule mockitoRule = MockitoJUnit.rule();
68+
69+
@Rule
70+
public WireMockRule wireMockRule = new WireMockRule(WireMockConfiguration.wireMockConfig()
71+
.jettyAcceptors(Runtime.getRuntime().availableProcessors())
72+
.dynamicPort());
73+
74+
@Mock
75+
private ObjectReceiver<Reader> receiver;
76+
77+
@Captor
78+
private ArgumentCaptor<Reader> processedObject;
79+
80+
@Test
81+
public void shouldPerformGetRequestWithInputAsUrlByDefault() throws IOException {
82+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {});
83+
}
84+
85+
@Test
86+
public void shouldPerformGetRequestWithUrlParameter() throws IOException {
87+
shouldPerformRequest(TEST_STRING, HttpOpener.Method.GET, (o, u) -> {
88+
o.setUrl(u);
89+
});
90+
}
91+
92+
@Test
93+
public void shouldPerformPostRequestWithInputAsUrl() throws IOException {
94+
shouldPerformRequest(TEST_URL, HttpOpener.Method.POST, (o, u) -> {
95+
o.setMethod(HttpOpener.Method.POST);
96+
o.setBody(REQUEST_BODY);
97+
});
98+
}
99+
100+
@Test
101+
public void shouldPerformPostRequestWithUrlParameter() throws IOException {
102+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.POST, (o, u) -> {
103+
o.setMethod(HttpOpener.Method.POST);
104+
o.setUrl(u);
105+
});
106+
}
107+
108+
@Test
109+
public void shouldPerformPostRequestWithBodyParameter() throws IOException {
110+
shouldPerformRequest(TEST_STRING, HttpOpener.Method.POST, (o, u) -> {
111+
o.setMethod(HttpOpener.Method.POST);
112+
o.setUrl(u);
113+
o.setBody(REQUEST_BODY);
114+
});
115+
}
116+
117+
@Test
118+
public void shouldPerformPostRequestInsteadOfGetWithBodyParameter() throws IOException {
119+
shouldPerformRequest(TEST_URL, HttpOpener.Method.POST, (o, u) -> {
120+
o.setMethod(HttpOpener.Method.GET);
121+
o.setBody(REQUEST_BODY);
122+
});
123+
}
124+
125+
@Test
126+
public void shouldPerformPostRequestInsteadOfGetWithInputAsBodyParameter() throws IOException {
127+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.POST, (o, u) -> {
128+
o.setMethod(HttpOpener.Method.GET);
129+
o.setUrl(u);
130+
o.setBody("@-");
131+
});
132+
}
133+
134+
@Test
135+
public void shouldPerformGetRequestWithoutBodyWithAlreadyUsedInputAsBodyParameter() throws IOException {
136+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {
137+
o.setBody("@-");
138+
});
139+
}
140+
141+
@Test
142+
public void shouldPerformPutRequestWithUrlParameter() throws IOException {
143+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.PUT, (o, u) -> {
144+
o.setMethod(HttpOpener.Method.PUT);
145+
o.setUrl(u);
146+
});
147+
}
148+
149+
@Test
150+
public void shouldPerformPutRequestWithBodyParameter() throws IOException {
151+
shouldPerformRequest(TEST_STRING, HttpOpener.Method.PUT, (o, u) -> {
152+
o.setMethod(HttpOpener.Method.PUT);
153+
o.setUrl(u);
154+
o.setBody(REQUEST_BODY);
155+
});
156+
}
157+
158+
@Test
159+
public void shouldPerformDeleteRequestWithUrlParameter() throws IOException {
160+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.DELETE, (o, u) -> {
161+
o.setMethod(HttpOpener.Method.DELETE);
162+
o.setUrl(u);
163+
});
164+
}
165+
166+
@Test
167+
public void shouldPerformHeadRequestWithUrlParameter() throws IOException {
168+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.HEAD, (o, u) -> {
169+
o.setMethod(HttpOpener.Method.HEAD);
170+
o.setUrl(u);
171+
});
172+
}
173+
174+
@Test
175+
public void shouldPerformOptionsRequestWithUrlParameter() throws IOException {
176+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.OPTIONS, (o, u) -> {
177+
o.setMethod(HttpOpener.Method.OPTIONS);
178+
o.setUrl(u);
179+
});
180+
}
181+
182+
@Test
183+
public void shouldPerformTraceRequestWithUrlParameter() throws IOException {
184+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.TRACE, (o, u) -> {
185+
o.setMethod(HttpOpener.Method.TRACE);
186+
o.setUrl(u);
187+
});
188+
}
189+
190+
@Test
191+
public void shouldPerformGetRequestWithAcceptParameter() throws IOException {
192+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {
193+
o.setAccept(TEST_STRING);
194+
}, "Accept");
195+
}
196+
197+
@Test
198+
public void shouldPerformGetRequestWithSingleValuedHeaderParameter() throws IOException {
199+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {
200+
o.setHeader("x-api-key: " + TEST_STRING);
201+
}, "x-api-key");
202+
}
203+
204+
@Test
205+
public void shouldPerformGetRequestWithMultiValuedHeaderParameter() throws IOException {
206+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {
207+
o.setHeader("x-api-key: " + TEST_STRING + "\nx-other-header: " + TEST_STRING);
208+
}, "x-api-key", "x-other-header");
209+
}
210+
211+
@Test
212+
public void shouldPerformGetRequestWithMultipledHeaderParameters() throws IOException {
213+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {
214+
o.setHeader("x-api-key: " + TEST_STRING);
215+
o.setHeader("x-other-header: " + TEST_STRING);
216+
}, "x-api-key", "x-other-header");
217+
}
218+
219+
@Test
220+
public void shouldPerformPostRequestWithContentTypeParameter() throws IOException {
221+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.POST, (o, u) -> {
222+
o.setMethod(HttpOpener.Method.POST);
223+
o.setUrl(u);
224+
o.setContentType(TEST_STRING);
225+
}, "Content-Type");
226+
}
227+
228+
@Test
229+
public void shouldPerformPostRequestWithEncodingParameter() throws IOException {
230+
final String encoding = "ISO-8859-1";
231+
final String header = "Accept-Charset";
232+
final StringValuePattern value = WireMock.equalTo(encoding);
233+
234+
try {
235+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.POST, (o, u) -> {
236+
o.setMethod(HttpOpener.Method.POST);
237+
o.setUrl(u);
238+
o.setEncoding(encoding);
239+
}, s -> s.withHeader(header, value), q -> q.withHeader(header, value), null);
240+
}
241+
catch (final ComparisonFailure e) {
242+
Assert.assertEquals("expected:<response b[ö]dy> but was:<response b[ö]dy>", e.getMessage());
243+
}
244+
}
245+
246+
@Test
247+
public void shouldPerformPostRequestWithEncodingParameterAndContentEncodingResponseHeader() throws IOException {
248+
final String encoding = "ISO-8859-1";
249+
final String header = "Accept-Charset";
250+
final StringValuePattern value = WireMock.equalTo(encoding);
251+
252+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.POST, (o, u) -> {
253+
o.setMethod(HttpOpener.Method.POST);
254+
o.setUrl(u);
255+
o.setEncoding(encoding);
256+
},
257+
s -> s.withHeader(header, value),
258+
q -> q.withHeader(header, value),
259+
r -> r.withHeader("Content-Encoding", "UTF-8")
260+
);
261+
}
262+
263+
@Test
264+
public void shouldPerformGetRequestWithErrorResponse() throws IOException {
265+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {},
266+
null, null, WireMock.badRequest().withBody(RESPONSE_BODY), "ERROR: " + TEST_ERROR);
267+
}
268+
269+
@Test
270+
public void shouldPerformGetRequestWithErrorResponseAndErrorPrefixParameter() throws IOException {
271+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> o.setErrorPrefix(TEST_STRING),
272+
null, null, WireMock.badRequest().withBody(RESPONSE_BODY), TEST_STRING + TEST_ERROR);
273+
}
274+
275+
@Test
276+
public void shouldPerformGetRequestWithErrorResponseAndWithoutErrorPrefixParameter() throws IOException {
277+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> o.setErrorPrefix(null),
278+
null, null, WireMock.badRequest().withBody(RESPONSE_BODY), TEST_ERROR);
279+
}
280+
281+
private void shouldPerformRequest(final String input, final HttpOpener.Method method, final BiConsumer<HttpOpener, String> consumer, final String... headers) throws IOException {
282+
shouldPerformRequest(input, method, consumer,
283+
s -> Arrays.stream(headers).forEach(h -> s.withHeader(h, TEST_VALUE)),
284+
q -> Arrays.stream(headers).forEach(h -> q.withHeader(h, TEST_VALUE)), null);
285+
}
286+
287+
private void shouldPerformRequest(final String input, final HttpOpener.Method method, final BiConsumer<HttpOpener, String> consumer, final Consumer<MappingBuilder> stubConsumer, final Consumer<RequestPatternBuilder> requestConsumer, final Consumer<ResponseDefinitionBuilder> responseConsumer) throws IOException {
288+
final ResponseDefinitionBuilder response = WireMock.ok().withBody(RESPONSE_BODY);
289+
if (responseConsumer != null) {
290+
responseConsumer.accept(response);
291+
}
292+
293+
shouldPerformRequest(input, method,
294+
consumer, stubConsumer, requestConsumer,
295+
response, method.getResponseHasBody() ? RESPONSE_BODY : "");
296+
}
297+
298+
private void shouldPerformRequest(final String input, final HttpOpener.Method method, final BiConsumer<HttpOpener, String> consumer, final Consumer<MappingBuilder> stubConsumer, final Consumer<RequestPatternBuilder> requestConsumer, final ResponseDefinitionBuilder response, final String responseBody) throws IOException {
299+
final String baseUrl = wireMockRule.baseUrl();
300+
final String url = String.format(TEST_URL, baseUrl);
301+
302+
final String methodName = method.name();
303+
final UrlPattern urlPattern = WireMock.urlPathEqualTo(TEST_PATH);
304+
305+
final HttpOpener opener = new HttpOpener();
306+
opener.setReceiver(receiver);
307+
consumer.accept(opener, url);
308+
309+
final MappingBuilder stub = WireMock.request(methodName, urlPattern).willReturn(response);
310+
if (stubConsumer != null) {
311+
stubConsumer.accept(stub);
312+
}
313+
314+
final RequestPatternBuilder request = new RequestPatternBuilder(RequestMethod.fromString(methodName), urlPattern)
315+
.withRequestBody(method.getRequestHasBody() ? WireMock.equalTo(REQUEST_BODY) : WireMock.absent());
316+
if (requestConsumer != null) {
317+
requestConsumer.accept(request);
318+
}
319+
320+
WireMock.stubFor(stub);
321+
322+
opener.process(String.format(input, baseUrl));
323+
opener.closeStream();
324+
325+
WireMock.verify(request);
326+
327+
Mockito.verify(receiver).process(processedObject.capture());
328+
Assert.assertEquals(responseBody, ResourceUtil.readAll(processedObject.getValue()));
329+
}
330+
331+
}

0 commit comments

Comments
 (0)