Skip to content

Commit 701c217

Browse files
committed
test: proxy and ssl configuration
1 parent 3518c9b commit 701c217

2 files changed

Lines changed: 99 additions & 21 deletions

File tree

src/main/java/com/factset/sdk/utils/authentication/ConfidentialClient.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,25 @@ protected ConfidentialClient(final Configuration config, final TokenRequestBuild
166166
this.tokenRequestBuilder = tokReqBuilder.uri(this.providerMetadata.getTokenEndpointURI());
167167
}
168168

169+
/**
170+
* Creates a new ConfidentialClient. When setting up the OAuth 2.0 client, this constructor reaches out to
171+
* FactSet's well-known URI to retrieve metadata about its authorization server. This information along with
172+
* information about the OAuth 2.0 client is stored and used whenever a new access token is fetched.
173+
*
174+
* @param config Configuration object.
175+
* @param tokReqBuilder The TokenRequest builder, used to build custom TokenRequest instances.
176+
* @param requestOptions Object that can configure options like proxy and SSL settings
177+
* @throws AuthServerMetadataContentException If Meta Issuer or Meta Token Endpoint is missing.
178+
* @throws AuthServerMetadataException If reading from URL is unsuccessful.
179+
* @throws NullPointerException Unchecked exception, if config is null.
180+
*/
181+
protected ConfidentialClient(final Configuration config, final TokenRequestBuilder tokReqBuilder, RequestOptions requestOptions)
182+
throws AuthServerMetadataContentException,
183+
AuthServerMetadataException {
184+
this(config, requestOptions);
185+
this.tokenRequestBuilder = tokReqBuilder.uri(this.providerMetadata.getTokenEndpointURI());
186+
}
187+
169188
/**
170189
* Returns an access token that can be used for authentication. If the cache contains a valid access token,
171190
* it's returned. Otherwise, a new access token is retrieved from FactSet's authorization server. The access

src/test/java/com/factset/sdk/utils/authentication/ConfidentialClientTest.java

Lines changed: 80 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.junit.jupiter.api.BeforeAll;
99
import org.junit.jupiter.api.Test;
1010

11+
import javax.net.ssl.HttpsURLConnection;
1112
import java.io.File;
1213
import java.io.IOException;
1314
import java.net.*;
@@ -149,9 +150,11 @@ void confidentialClientValidPathValidConfigCannotGetInputStreamThrowsAuthServerM
149150
}
150151

151152
@Test
152-
void confidentialClientValidPathValidConfigMissingIssuerAndTokenEndpointThrowsAuthServerMetadataContentException() {
153+
void confidentialClientValidPathValidConfigMissingIssuerAndTokenEndpointThrowsAuthServerMetadataContentException() throws Exception {
154+
HttpURLConnection mockedConn = mock(HttpURLConnection.class);
155+
URL mockedURL = getUrlMockResponse("emptyJson.txt", mockedConn);
153156
assertThrows(AuthServerMetadataContentException.class,
154-
() -> new ConfidentialClient(getConfigSpyMockedResponse("emptyJson.txt", "validConfig.txt")));
157+
() -> new ConfidentialClient(getConfigSpyMockedResponse(mockedURL, "validConfig.txt")));
155158
}
156159

157160
@Test
@@ -163,7 +166,8 @@ void confidentialClientValidPathValidConfigCustomWellKnownUriInitialisesWithNoEx
163166
"https://test.test.com/.test-test/test-test");
164167

165168
// If this confidential client is instantiated without exceptions, that results in a passing test.
166-
URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt");
169+
HttpURLConnection mockedConn = mock(HttpURLConnection.class);
170+
URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn);
167171
Configuration configurationSpy = spy(configuration);
168172
when(configurationSpy.getWellKnownUrl()).thenReturn(mockedURL);
169173
new ConfidentialClient(configurationSpy);
@@ -174,10 +178,27 @@ void confidentialClientValidPathValidConfigCustomWellKnownUriInitialisesWithNoEx
174178
void confidentialClientValidConfigInitialisesWithNoException() {
175179
assertDoesNotThrow(() -> {
176180
// If this confidential client is instantiated without exceptions, that results in a passing test.
177-
new ConfidentialClient(getConfigSpyMockedResponse("exampleResponseWellKnownUri.txt", "validConfig.txt"));
181+
HttpURLConnection mockedConn = mock(HttpURLConnection.class);
182+
URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn);
183+
new ConfidentialClient(getConfigSpyMockedResponse(mockedURL, "validConfig.txt"));
178184
});
179185
}
180186

187+
@Test
188+
void confidentialClientValidConfigInitialisesWithRequestOptions() throws Exception {
189+
Proxy mockProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8080));
190+
RequestOptions reqOptions = RequestOptions.builder().proxy(mockProxy).build();
191+
192+
HttpsURLConnection mockedConn = mock(HttpsURLConnection.class);
193+
URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn);
194+
Configuration config = getConfigSpyMockedResponse(mockedURL, "validConfig.txt");
195+
new ConfidentialClient(config, reqOptions);
196+
197+
verify(mockedURL).openConnection(mockProxy);
198+
verify(mockedConn).setHostnameVerifier(reqOptions.getHostnameVerifier());
199+
verify(mockedConn).setSSLSocketFactory(reqOptions.getSslSocketFactory());
200+
}
201+
181202
@Test
182203
void getAccessTokenCallingWithFailedSigningRaisesSigningJwsException() throws Exception {
183204
try {
@@ -195,14 +216,18 @@ void getAccessTokenCallingWithFailedSigningRaisesSigningJwsException() throws Ex
195216
@Test
196217
void getAccessTokenCallingWithErroneousResponseRaisesAccessTokenException() throws Exception {
197218
try {
219+
HttpURLConnection mockedConn = mock(HttpURLConnection.class);
220+
URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn);
198221
Configuration configurationMock = ConfidentialClientTest.getConfigSpyMockedResponse(
199-
"exampleResponseWellKnownUri.txt", "validConfig.txt"
222+
mockedURL, "validConfig.txt"
200223
);
201224

225+
HTTPRequest mockedRequest = mock(HTTPRequest.class);
202226
TokenRequestBuilder tokenRequestBuilderSpy = ConfidentialClientTest.createTokenRequestBuilderSpy(
203227
HTTPResponse.SC_UNAUTHORIZED,
204228
"{\"error_description\":\"Unauthorized access.\",\"error\":\"invalid_request\"}",
205-
false
229+
false,
230+
mockedRequest
206231
);
207232

208233
ConfidentialClient confidentialClientSpy = spy(new ConfidentialClient(configurationMock, tokenRequestBuilderSpy));
@@ -215,14 +240,18 @@ void getAccessTokenCallingWithErroneousResponseRaisesAccessTokenException() thro
215240

216241
@Test
217242
void getAccessTokenCalledForTheFirstTimeReturnsANewAccessToken() throws Exception {
243+
HttpURLConnection mockedConn = mock(HttpURLConnection.class);
244+
URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn);
218245
Configuration configurationMock = ConfidentialClientTest.getConfigSpyMockedResponse(
219-
"exampleResponseWellKnownUri.txt", "validConfig.txt"
246+
mockedURL, "validConfig.txt"
220247
);
221248

249+
HTTPRequest mockedRequest = mock(HTTPRequest.class);
222250
TokenRequestBuilder tokenRequestBuilderSpy = ConfidentialClientTest.createTokenRequestBuilderSpy(
223251
HTTPResponse.SC_OK,
224252
"{\"access_token\":\"test token\",\"token_type\":\"Bearer\",\"expires_in\":899}",
225-
true
253+
true,
254+
mockedRequest
226255
);
227256

228257
ConfidentialClient confidentialClientSpy = spy(new ConfidentialClient(configurationMock, tokenRequestBuilderSpy));
@@ -231,10 +260,38 @@ void getAccessTokenCalledForTheFirstTimeReturnsANewAccessToken() throws Exceptio
231260
assertEquals("test token", accessToken);
232261
}
233262

263+
@Test
264+
void getAccessTokenCalledWithRequestOptionsSetsProxyAndSSLSettings() throws Exception {
265+
HttpURLConnection mockedConn = mock(HttpURLConnection.class);
266+
URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn);
267+
Configuration configurationMock = ConfidentialClientTest.getConfigSpyMockedResponse(
268+
mockedURL, "validConfig.txt"
269+
);
270+
271+
HTTPRequest mockedRequest = mock(HTTPRequest.class);
272+
TokenRequestBuilder tokenRequestBuilderSpy = ConfidentialClientTest.createTokenRequestBuilderSpy(
273+
HTTPResponse.SC_OK,
274+
"{\"access_token\":\"test token\",\"token_type\":\"Bearer\",\"expires_in\":899}",
275+
true,
276+
mockedRequest
277+
);
278+
279+
Proxy mockProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 8080));
280+
RequestOptions reqOptions = RequestOptions.builder().proxy(mockProxy).build();
281+
ConfidentialClient confidentialClientSpy = spy(new ConfidentialClient(configurationMock, tokenRequestBuilderSpy, reqOptions));
282+
confidentialClientSpy.getAccessToken();
283+
284+
verify(mockedRequest).setProxy(mockProxy);
285+
verify(mockedRequest).setHostnameVerifier(reqOptions.getHostnameVerifier());
286+
verify(mockedRequest).setSSLSocketFactory(reqOptions.getSslSocketFactory());
287+
}
288+
234289
@Test
235290
void getAccessTokenCalledTwiceBeforeExpirationReturnsSameAccessToken() throws Exception {
291+
HttpURLConnection mockedConn = mock(HttpURLConnection.class);
292+
URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn);
236293
Configuration configurationMock = ConfidentialClientTest.getConfigSpyMockedResponse(
237-
"exampleResponseWellKnownUri.txt", "validConfig.txt"
294+
mockedURL, "validConfig.txt"
238295
);
239296

240297
HTTPResponse res = new HTTPResponse(HTTPResponse.SC_OK);
@@ -265,8 +322,10 @@ void getAccessTokenCalledTwiceBeforeExpirationReturnsSameAccessToken() throws Ex
265322

266323
@Test
267324
void getAccessTokenCallingBeforeAndAfterExpirationReturnsDifferentAccessToken() throws Exception {
325+
HttpURLConnection mockedConn = mock(HttpURLConnection.class);
326+
URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn);
268327
Configuration configurationMock = ConfidentialClientTest.getConfigSpyMockedResponse(
269-
"exampleResponseWellKnownUri.txt", "validConfig.txt"
328+
mockedURL, "validConfig.txt"
270329
);
271330

272331
HTTPResponse res1 = new HTTPResponse(HTTPResponse.SC_OK);
@@ -302,14 +361,18 @@ void getAccessTokenCallingBeforeAndAfterExpirationReturnsDifferentAccessToken()
302361
@Test
303362
void getAccessTokenCallingWithSendErrorRaisesAccessTokenException() throws Exception {
304363
try {
364+
HttpURLConnection mockedConn = mock(HttpURLConnection.class);
365+
URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn);
305366
Configuration configurationMock = ConfidentialClientTest.getConfigSpyMockedResponse(
306-
"exampleResponseWellKnownUri.txt", "validConfig.txt"
367+
mockedURL, "validConfig.txt"
307368
);
308369

370+
HTTPRequest mockedRequest = mock(HTTPRequest.class);
309371
TokenRequestBuilder tokenRequestBuilderSpy = ConfidentialClientTest.createTokenRequestBuilderSpy(
310372
HTTPResponse.SC_OK,
311373
"{\"error_description\":\"Invalid request.\",\"error\":\"invalid_request\"}",
312-
false
374+
false,
375+
mockedRequest
313376
);
314377

315378
ConfidentialClient confidentialClientSpy = spy(new ConfidentialClient(configurationMock, tokenRequestBuilderSpy));
@@ -321,19 +384,17 @@ void getAccessTokenCallingWithSendErrorRaisesAccessTokenException() throws Excep
321384
}
322385
}
323386

324-
private static URL getUrlMockResponse(String stringFile) throws IOException {
387+
private static URL getUrlMockResponse(String stringFile, HttpURLConnection mockedConn) throws IOException {
325388
final File file = new File(String.valueOf(Paths.get(String.valueOf(pathToResources), stringFile)));
326389

327390
URL mockedUrl = mock(URL.class);
328-
HttpURLConnection mockedConn = mock(HttpURLConnection.class);
329391
when(mockedUrl.openConnection(any(Proxy.class))).thenReturn(mockedConn);
330392
when(mockedConn.getInputStream()).thenReturn(Files.newInputStream(file.toPath()));
331393

332394
return mockedUrl;
333395
}
334396

335-
private static Configuration getConfigSpyMockedResponse(String urlResponse, String configFile) throws IOException, ConfigurationException {
336-
URL mockedURL = getUrlMockResponse(urlResponse);
397+
private static Configuration getConfigSpyMockedResponse(URL mockedURL, String configFile) throws ConfigurationException {
337398
Configuration configuration = new Configuration(String.valueOf(Paths.get(pathToResources.toString(), configFile)));
338399
Configuration configurationSpy = spy(configuration);
339400
when(configurationSpy.getWellKnownUrl()).thenReturn(mockedURL);
@@ -352,7 +413,7 @@ private static Configuration getConfigSpyThrowsIOException(String configFile) th
352413
}
353414

354415
private static TokenRequestBuilder createTokenRequestBuilderSpy(int statusCode, String resContent,
355-
boolean requiresHeader) throws URISyntaxException,
416+
boolean requiresHeader, HTTPRequest mockedRequest) throws URISyntaxException,
356417
IOException {
357418
HTTPResponse res = new HTTPResponse(statusCode);
358419
res.setContent(resContent);
@@ -367,11 +428,9 @@ private static TokenRequestBuilder createTokenRequestBuilderSpy(int statusCode,
367428

368429
TokenRequestBuilder tokenRequestBuilderSpy = spy(new TokenRequestBuilder());
369430

370-
HTTPRequest httpRequestMock = mock(HTTPRequest.class);
371-
372431
doReturn(tokenRequestMock).when(tokenRequestBuilderSpy).build();
373-
doReturn(httpRequestMock).when(tokenRequestMock).toHTTPRequest();
374-
doReturn(res).when(httpRequestMock).send();
432+
doReturn(mockedRequest).when(tokenRequestMock).toHTTPRequest();
433+
doReturn(res).when(mockedRequest).send();
375434

376435
return tokenRequestBuilderSpy;
377436
}

0 commit comments

Comments
 (0)