|
7 | 7 | import com.nimbusds.oauth2.sdk.http.HTTPResponse; |
8 | 8 | import org.junit.jupiter.api.BeforeAll; |
9 | 9 | import org.junit.jupiter.api.Test; |
| 10 | +import org.mockito.stubbing.OngoingStubbing; |
10 | 11 |
|
11 | 12 | import javax.net.ssl.HttpsURLConnection; |
12 | 13 | import java.io.File; |
@@ -253,24 +254,10 @@ void getAccessTokenCallingWithErroneousResponseRaisesAccessTokenException() thro |
253 | 254 |
|
254 | 255 | @Test |
255 | 256 | void getAccessTokenCalledForTheFirstTimeReturnsANewAccessToken() throws Exception { |
256 | | - HttpURLConnection mockedConn = mock(HttpURLConnection.class); |
257 | | - URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn); |
258 | | - Configuration configurationMock = ConfidentialClientTest.getConfigSpyMockedResponse( |
259 | | - mockedURL, "validConfig.txt" |
260 | | - ); |
261 | | - |
262 | | - HTTPRequest mockedRequest = mock(HTTPRequest.class); |
263 | | - TokenRequestBuilder tokenRequestBuilderSpy = ConfidentialClientTest.createTokenRequestBuilderSpy( |
264 | | - HTTPResponse.SC_OK, |
265 | | - "{\"access_token\":\"test token\",\"token_type\":\"Bearer\",\"expires_in\":899}", |
266 | | - true, |
267 | | - mockedRequest |
268 | | - ); |
269 | | - |
270 | | - ConfidentialClient confidentialClientSpy = spy(new ConfidentialClient(configurationMock, tokenRequestBuilderSpy)); |
271 | | - String accessToken = confidentialClientSpy.getAccessToken(); |
272 | | - |
| 257 | + TestHarness harness = createClientWithTokens(899, "test token"); |
| 258 | + String accessToken = harness.client.getAccessToken(); |
273 | 259 | assertEquals("test token", accessToken); |
| 260 | + verify(harness.httpRequestMock, times(1)).send(); |
274 | 261 | } |
275 | 262 |
|
276 | 263 | @Test |
@@ -301,100 +288,93 @@ void getAccessTokenCalledWithRequestOptionsSetsProxyAndSSLSettings() throws Exce |
301 | 288 |
|
302 | 289 | @Test |
303 | 290 | void getAccessTokenCalledTwiceBeforeExpirationReturnsSameAccessToken() throws Exception { |
304 | | - HttpURLConnection mockedConn = mock(HttpURLConnection.class); |
305 | | - URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn); |
306 | | - Configuration configurationMock = ConfidentialClientTest.getConfigSpyMockedResponse( |
307 | | - mockedURL, "validConfig.txt" |
308 | | - ); |
309 | | - |
310 | | - HTTPResponse res = new HTTPResponse(HTTPResponse.SC_OK); |
311 | | - res.setContent("{\"access_token\":\"test token\",\"token_type\":\"Bearer\",\"expires_in\":899}"); |
312 | | - res.setHeader("Content-Type", "application/json;charset=utf-8"); |
313 | | - |
314 | | - AuthorizationGrant grant = new UnitTestGrant(); |
315 | | - URI uriSpy = spy(new URI("https://test.test.com/.test-test/test-test")); |
316 | | - TokenRequest tokenRequestMock = spy(new TokenRequest(uriSpy, grant, new Scope())); |
317 | | - |
318 | | - TokenRequestBuilder tokenRequestBuilderSpy = spy(new TokenRequestBuilder()); |
| 291 | + TestHarness harness = createClientWithTokens(899, "test token"); |
| 292 | + String accessToken1 = harness.client.getAccessToken(); |
| 293 | + String accessToken2 = harness.client.getAccessToken(); |
| 294 | + assertEquals("test token", accessToken1); |
| 295 | + assertEquals("test token", accessToken2); |
| 296 | + verify(harness.httpRequestMock, times(1)).send(); |
| 297 | + } |
319 | 298 |
|
320 | | - HTTPRequest httpRequestMock = mock(HTTPRequest.class); |
| 299 | + @Test |
| 300 | + void getAccessTokenCallingBeforeAndAfterExpirationReturnsDifferentAccessToken() throws Exception { |
| 301 | + TestHarness harness = createClientWithTokens(0, "test token 1", "test token 2"); |
| 302 | + String accessToken1 = harness.client.getAccessToken(); |
| 303 | + String accessToken2 = harness.client.getAccessToken(); |
| 304 | + assertEquals("test token 1", accessToken1); |
| 305 | + assertEquals("test token 2", accessToken2); |
| 306 | + verify(harness.httpRequestMock, times(2)).send(); |
| 307 | + } |
321 | 308 |
|
322 | | - doReturn(tokenRequestMock).when(tokenRequestBuilderSpy).build(); |
323 | | - doReturn(httpRequestMock).when(tokenRequestMock).toHTTPRequest(); |
324 | | - doReturn(res).when(httpRequestMock).send(); |
| 309 | + @Test |
| 310 | + void getAccessTokenWithForceRefreshTrueAlwaysFetchesNewToken() throws Exception { |
| 311 | + TestHarness harness = createClientWithTokens(899, "token1", "token2"); |
| 312 | + String tokenA = harness.client.getAccessToken(true); |
| 313 | + String tokenB = harness.client.getAccessToken(true); |
| 314 | + assertEquals("token1", tokenA); |
| 315 | + assertEquals("token2", tokenB); |
| 316 | + verify(harness.httpRequestMock, times(2)).send(); |
| 317 | + } |
325 | 318 |
|
326 | | - ConfidentialClient confidentialClientSpy = spy(new ConfidentialClient(configurationMock, tokenRequestBuilderSpy)); |
| 319 | + @Test |
| 320 | + void getAccessTokenWithForceRefreshFalseReturnsCachedTokenIfValid() throws Exception { |
| 321 | + TestHarness harness = createClientWithTokens(899, "tokenX"); |
| 322 | + String token1 = harness.client.getAccessToken(false); |
| 323 | + String token2 = harness.client.getAccessToken(false); |
| 324 | + assertEquals("tokenX", token1); |
| 325 | + assertEquals("tokenX", token2); |
| 326 | + verify(harness.httpRequestMock, times(1)).send(); |
| 327 | + } |
327 | 328 |
|
328 | | - String accessToken1 = confidentialClientSpy.getAccessToken(); |
329 | | - String accessToken2 = confidentialClientSpy.getAccessToken(); |
| 329 | + @Test |
| 330 | + void getAccessTokenForceRefreshThenCachedReturnsCorrectTokens() throws Exception { |
| 331 | + TestHarness harness = createClientWithTokens(899, "tokenA", "tokenB"); |
| 332 | + String tokenA = harness.client.getAccessToken(true); // force fetch first (tokenA) |
| 333 | + String tokenB = harness.client.getAccessToken(false); // should use cached tokenA, not fetch tokenB |
| 334 | + assertEquals("tokenA", tokenA); |
| 335 | + assertEquals("tokenA", tokenB); |
| 336 | + verify(harness.httpRequestMock, times(1)).send(); |
| 337 | + } |
330 | 338 |
|
331 | | - assertEquals("test token", accessToken1); |
332 | | - assertEquals("test token", accessToken2); |
333 | | - verify(httpRequestMock).send(); |
| 339 | + private static class TestHarness { |
| 340 | + final ConfidentialClient client; |
| 341 | + final HTTPRequest httpRequestMock; |
| 342 | + TestHarness(ConfidentialClient client, HTTPRequest httpRequestMock) { |
| 343 | + this.client = client; |
| 344 | + this.httpRequestMock = httpRequestMock; |
| 345 | + } |
334 | 346 | } |
335 | 347 |
|
336 | | - @Test |
337 | | - void getAccessTokenCallingBeforeAndAfterExpirationReturnsDifferentAccessToken() throws Exception { |
| 348 | + private static TestHarness createClientWithTokens(int expiresInSeconds, String... tokens) throws Exception { |
338 | 349 | HttpURLConnection mockedConn = mock(HttpURLConnection.class); |
339 | 350 | URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn); |
340 | | - Configuration configurationMock = ConfidentialClientTest.getConfigSpyMockedResponse( |
341 | | - mockedURL, "validConfig.txt" |
342 | | - ); |
343 | | - |
344 | | - HTTPResponse res1 = new HTTPResponse(HTTPResponse.SC_OK); |
345 | | - res1.setContent("{\"access_token\":\"test token 1\",\"token_type\":\"Bearer\",\"expires_in\":0}"); |
346 | | - res1.setHeader("Content-Type", "application/json;charset=utf-8"); |
347 | | - |
348 | | - HTTPResponse res2 = new HTTPResponse(HTTPResponse.SC_OK); |
349 | | - res2.setContent("{\"access_token\":\"test token 2\",\"token_type\":\"Bearer\",\"expires_in\":0}"); |
350 | | - res2.setHeader("Content-Type", "application/json;charset=utf-8"); |
| 351 | + Configuration configurationMock = getConfigSpyMockedResponse(mockedURL, "validConfig.txt"); |
351 | 352 |
|
352 | 353 | AuthorizationGrant grant = new UnitTestGrant(); |
353 | 354 | URI uriSpy = spy(new URI("https://test.test.com/.test-test/test-test")); |
354 | 355 | TokenRequest tokenRequestMock = spy(new TokenRequest(uriSpy, grant, new Scope())); |
355 | | - |
356 | 356 | TokenRequestBuilder tokenRequestBuilderSpy = spy(new TokenRequestBuilder()); |
357 | | - |
358 | 357 | HTTPRequest httpRequestMock = mock(HTTPRequest.class); |
359 | 358 |
|
| 359 | + OngoingStubbing<HTTPResponse> stubbing = null; |
| 360 | + for (String token : tokens) { |
| 361 | + HTTPResponse res = new HTTPResponse(HTTPResponse.SC_OK); |
| 362 | + String body = String.format("{\"access_token\":\"%s\",\"token_type\":\"Bearer\",\"expires_in\":%d}", token, expiresInSeconds); |
| 363 | + res.setContent(body); |
| 364 | + res.setHeader("Content-Type", "application/json;charset=utf-8"); |
| 365 | + if (stubbing == null) { |
| 366 | + stubbing = when(httpRequestMock.send()); |
| 367 | + stubbing = stubbing.thenReturn(res); |
| 368 | + } else { |
| 369 | + stubbing = stubbing.thenReturn(res); |
| 370 | + } |
| 371 | + } |
| 372 | + |
360 | 373 | doReturn(tokenRequestMock).when(tokenRequestBuilderSpy).build(); |
361 | 374 | doReturn(httpRequestMock).when(tokenRequestMock).toHTTPRequest(); |
362 | | - doReturn(res1).doReturn(res2).when(httpRequestMock).send(); |
363 | 375 |
|
364 | 376 | ConfidentialClient confidentialClientSpy = spy(new ConfidentialClient(configurationMock, tokenRequestBuilderSpy)); |
365 | | - |
366 | | - String accessToken1 = confidentialClientSpy.getAccessToken(); |
367 | | - String accessToken2 = confidentialClientSpy.getAccessToken(); |
368 | | - |
369 | | - assertEquals("test token 1", accessToken1); |
370 | | - assertEquals("test token 2", accessToken2); |
371 | | - verify(httpRequestMock, times(2)).send(); |
372 | | - } |
373 | | - |
374 | | - @Test |
375 | | - void getAccessTokenCallingWithSendErrorRaisesAccessTokenException() throws Exception { |
376 | | - try { |
377 | | - HttpURLConnection mockedConn = mock(HttpURLConnection.class); |
378 | | - URL mockedURL = getUrlMockResponse("exampleResponseWellKnownUri.txt", mockedConn); |
379 | | - Configuration configurationMock = ConfidentialClientTest.getConfigSpyMockedResponse( |
380 | | - mockedURL, "validConfig.txt" |
381 | | - ); |
382 | | - |
383 | | - HTTPRequest mockedRequest = mock(HTTPRequest.class); |
384 | | - TokenRequestBuilder tokenRequestBuilderSpy = ConfidentialClientTest.createTokenRequestBuilderSpy( |
385 | | - HTTPResponse.SC_OK, |
386 | | - "{\"error_description\":\"Invalid request.\",\"error\":\"invalid_request\"}", |
387 | | - false, |
388 | | - mockedRequest |
389 | | - ); |
390 | | - |
391 | | - ConfidentialClient confidentialClientSpy = spy(new ConfidentialClient(configurationMock, tokenRequestBuilderSpy)); |
392 | | - |
393 | | - confidentialClientSpy.getAccessToken(); |
394 | | - fail(); |
395 | | - } catch (AccessTokenException e) { |
396 | | - assertEquals("Error attempting to get the access token", e.getMessage()); |
397 | | - } |
| 377 | + return new TestHarness(confidentialClientSpy, httpRequestMock); |
398 | 378 | } |
399 | 379 |
|
400 | 380 | private static URL getUrlMockResponse(String stringFile, HttpURLConnection mockedConn) throws IOException { |
|
0 commit comments