Skip to content

Commit 83628ad

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

File tree

2 files changed

+318
-0
lines changed

2 files changed

+318
-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: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
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(REQUEST_BODY, HttpOpener.Method.POST, (o, u) -> {
120+
o.setMethod(HttpOpener.Method.GET);
121+
o.setUrl(u);
122+
o.setBody(REQUEST_BODY);
123+
});
124+
}
125+
126+
@Test
127+
public void shouldPerformPutRequestWithUrlParameter() throws IOException {
128+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.PUT, (o, u) -> {
129+
o.setMethod(HttpOpener.Method.PUT);
130+
o.setUrl(u);
131+
});
132+
}
133+
134+
@Test
135+
public void shouldPerformPutRequestWithBodyParameter() throws IOException {
136+
shouldPerformRequest(TEST_STRING, HttpOpener.Method.PUT, (o, u) -> {
137+
o.setMethod(HttpOpener.Method.PUT);
138+
o.setUrl(u);
139+
o.setBody(REQUEST_BODY);
140+
});
141+
}
142+
143+
@Test
144+
public void shouldPerformDeleteRequestWithUrlParameter() throws IOException {
145+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.DELETE, (o, u) -> {
146+
o.setMethod(HttpOpener.Method.DELETE);
147+
o.setUrl(u);
148+
});
149+
}
150+
151+
@Test
152+
public void shouldPerformHeadRequestWithUrlParameter() throws IOException {
153+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.HEAD, (o, u) -> {
154+
o.setMethod(HttpOpener.Method.HEAD);
155+
o.setUrl(u);
156+
});
157+
}
158+
159+
@Test
160+
public void shouldPerformOptionsRequestWithUrlParameter() throws IOException {
161+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.OPTIONS, (o, u) -> {
162+
o.setMethod(HttpOpener.Method.OPTIONS);
163+
o.setUrl(u);
164+
});
165+
}
166+
167+
@Test
168+
public void shouldPerformTraceRequestWithUrlParameter() throws IOException {
169+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.TRACE, (o, u) -> {
170+
o.setMethod(HttpOpener.Method.TRACE);
171+
o.setUrl(u);
172+
});
173+
}
174+
175+
@Test
176+
public void shouldPerformGetRequestWithAcceptParameter() throws IOException {
177+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {
178+
o.setAccept(TEST_STRING);
179+
}, "Accept");
180+
}
181+
182+
@Test
183+
public void shouldPerformGetRequestWithSingleValuedHeaderParameter() throws IOException {
184+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {
185+
o.setHeader("x-api-key: " + TEST_STRING);
186+
}, "x-api-key");
187+
}
188+
189+
@Test
190+
public void shouldPerformGetRequestWithMultiValuedHeaderParameter() throws IOException {
191+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {
192+
o.setHeader("x-api-key: " + TEST_STRING + "\nx-other-header: " + TEST_STRING);
193+
}, "x-api-key", "x-other-header");
194+
}
195+
196+
@Test
197+
public void shouldPerformGetRequestWithMultipledHeaderParameters() throws IOException {
198+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {
199+
o.setHeader("x-api-key: " + TEST_STRING);
200+
o.setHeader("x-other-header: " + TEST_STRING);
201+
}, "x-api-key", "x-other-header");
202+
}
203+
204+
@Test
205+
public void shouldPerformPostRequestWithContentTypeParameter() throws IOException {
206+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.POST, (o, u) -> {
207+
o.setMethod(HttpOpener.Method.POST);
208+
o.setUrl(u);
209+
o.setContentType(TEST_STRING);
210+
}, "Content-Type");
211+
}
212+
213+
@Test
214+
public void shouldPerformPostRequestWithEncodingParameter() throws IOException {
215+
final String encoding = "ISO-8859-1";
216+
final String header = "Accept-Charset";
217+
final StringValuePattern value = WireMock.equalTo(encoding);
218+
219+
try {
220+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.POST, (o, u) -> {
221+
o.setMethod(HttpOpener.Method.POST);
222+
o.setUrl(u);
223+
o.setEncoding(encoding);
224+
}, s -> s.withHeader(header, value), q -> q.withHeader(header, value), null);
225+
}
226+
catch (final ComparisonFailure e) {
227+
Assert.assertEquals("expected:<response b[ö]dy> but was:<response b[ö]dy>", e.getMessage());
228+
}
229+
}
230+
231+
@Test
232+
public void shouldPerformPostRequestWithEncodingParameterAndContentEncodingResponseHeader() throws IOException {
233+
final String encoding = "ISO-8859-1";
234+
final String header = "Accept-Charset";
235+
final StringValuePattern value = WireMock.equalTo(encoding);
236+
237+
shouldPerformRequest(REQUEST_BODY, HttpOpener.Method.POST, (o, u) -> {
238+
o.setMethod(HttpOpener.Method.POST);
239+
o.setUrl(u);
240+
o.setEncoding(encoding);
241+
},
242+
s -> s.withHeader(header, value),
243+
q -> q.withHeader(header, value),
244+
r -> r.withHeader("Content-Encoding", "UTF-8")
245+
);
246+
}
247+
248+
@Test
249+
public void shouldPerformGetRequestWithErrorResponse() throws IOException {
250+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> {},
251+
null, null, WireMock.badRequest().withBody(RESPONSE_BODY), "ERROR: " + TEST_ERROR);
252+
}
253+
254+
@Test
255+
public void shouldPerformGetRequestWithErrorResponseAndErrorPrefixParameter() throws IOException {
256+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> o.setErrorPrefix(TEST_STRING),
257+
null, null, WireMock.badRequest().withBody(RESPONSE_BODY), TEST_STRING + TEST_ERROR);
258+
}
259+
260+
@Test
261+
public void shouldPerformGetRequestWithErrorResponseAndWithoutErrorPrefixParameter() throws IOException {
262+
shouldPerformRequest(TEST_URL, HttpOpener.Method.GET, (o, u) -> o.setErrorPrefix(null),
263+
null, null, WireMock.badRequest().withBody(RESPONSE_BODY), TEST_ERROR);
264+
}
265+
266+
private void shouldPerformRequest(final String input, final HttpOpener.Method method, final BiConsumer<HttpOpener, String> consumer, final String... headers) throws IOException {
267+
shouldPerformRequest(input, method, consumer,
268+
s -> Arrays.stream(headers).forEach(h -> s.withHeader(h, TEST_VALUE)),
269+
q -> Arrays.stream(headers).forEach(h -> q.withHeader(h, TEST_VALUE)), null);
270+
}
271+
272+
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 {
273+
final ResponseDefinitionBuilder response = WireMock.ok().withBody(RESPONSE_BODY);
274+
if (responseConsumer != null) {
275+
responseConsumer.accept(response);
276+
}
277+
278+
shouldPerformRequest(input, method,
279+
consumer, stubConsumer, requestConsumer,
280+
response, method.getResponseHasBody() ? RESPONSE_BODY : "");
281+
}
282+
283+
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 {
284+
final String baseUrl = wireMockRule.baseUrl();
285+
final String url = String.format(TEST_URL, baseUrl);
286+
287+
final String methodName = method.name();
288+
final UrlPattern urlPattern = WireMock.urlPathEqualTo(TEST_PATH);
289+
290+
final HttpOpener opener = new HttpOpener();
291+
opener.setReceiver(receiver);
292+
consumer.accept(opener, url);
293+
294+
final MappingBuilder stub = WireMock.request(methodName, urlPattern).willReturn(response);
295+
if (stubConsumer != null) {
296+
stubConsumer.accept(stub);
297+
}
298+
299+
final RequestPatternBuilder request = new RequestPatternBuilder(RequestMethod.fromString(methodName), urlPattern)
300+
.withRequestBody(method.getRequestHasBody() ? WireMock.equalTo(REQUEST_BODY) : WireMock.absent());
301+
if (requestConsumer != null) {
302+
requestConsumer.accept(request);
303+
}
304+
305+
WireMock.stubFor(stub);
306+
307+
opener.process(String.format(input, baseUrl));
308+
opener.closeStream();
309+
310+
WireMock.verify(request);
311+
312+
Mockito.verify(receiver).process(processedObject.capture());
313+
Assert.assertEquals(responseBody, ResourceUtil.readAll(processedObject.getValue()));
314+
}
315+
316+
}

0 commit comments

Comments
 (0)