Last active
April 8, 2024 17:19
-
-
Save ru-rocker/be9dce472ac7b059e04c1492d39ac2cc to your computer and use it in GitHub Desktop.
SpringWebFlux Unit Test with MockWebServer from OkHttp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<dependency> | |
<groupId>com.squareup.okhttp3</groupId> | |
<artifactId>okhttp</artifactId> | |
<version>4.12.0</version> | |
<scope>test</scope> | |
</dependency> | |
<dependency> | |
<groupId>com.squareup.okhttp3</groupId> | |
<artifactId>mockwebserver</artifactId> | |
<version>4.12.0</version> | |
<scope>test</scope> | |
</dependency> | |
<!-- https://mvnrepository.com/artifact/io.netty/netty-resolver-dns-native-macos --> | |
<dependency> | |
<groupId>io.netty</groupId> | |
<artifactId>netty-resolver-dns-native-macos</artifactId> | |
<version>4.1.68.Final</version> | |
<scope>test</scope> | |
<classifier>osx-aarch_64</classifier> | |
</dependency> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Service | |
public class TokenValidatorServiceImpl implements TokenValidatorService { | |
private String fileAttUrlPath; | |
private String fileAttRoute; | |
@Autowired | |
private ClientProperties clientProperties; | |
private final WebClient.Builder webClientBuilder; | |
private static final Logger LOG = LoggerFactory.getLogger(TokenValidatorServiceImpl.class); | |
public TokenValidatorServiceImpl(WebClient.Builder webClientBuilder) { | |
this.webClientBuilder = webClientBuilder; | |
} | |
@Override | |
public Mono<TokenInfo> validateToken(String tokenBearer) { | |
String url = URLUtil.buildFullUrl(StringUtil.strConcat(fileAttRoute, fileAttUrlPath)); | |
// @formatter:off | |
return webClientBuilder | |
.build() | |
.post() | |
.uri(url) | |
.accept(MediaType.APPLICATION_JSON) | |
.header(clientProperties.getAuthorizationHeader(), tokenBearer) | |
.body(BodyInserters.fromValue("parameters")) | |
.retrieve() | |
.bodyToMono(String.class) | |
.onErrorMap(throwable -> new RestClientException(throwable.getMessage())) | |
.flatMap(response -> { | |
LOG.info("Response : {}", response); | |
TokenInfo tokenInfo = JsonUtil.getObjectFromJson(response, TokenInfo.class); | |
return validateResponse(tokenBearer, tokenInfo); | |
}); | |
// @formatter:on | |
} | |
private Mono<TokenInfo> validateResponse(final String tokenBearer, final TokenInfo tokenInfo) { | |
if (tokenInfo == null || tokenInfo.getUser() == null) { | |
return Mono.error(new TokenNotFoundException("Invalid token. Please login again !!!")); | |
} | |
Integer responseCode = tokenInfo.getResponseCode(); | |
LOG.debug("Token Info : {} {}", tokenInfo, responseCode); | |
if (responseCode == null | |
|| responseCode != HttpStatus.OK.value() | |
|| StringUtils.isEmpty(tokenInfo.getUserGroups())) { | |
return Mono.error(new RoleNotFoundException( | |
"Either Insufficient authentication details or No role/group is mapped to the user")); | |
} | |
return Mono.just(tokenInfo); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class TokenValidatorServiceImplTest { | |
@Mock | |
ClientProperties clientProperties; | |
@InjectMocks | |
private TokenValidatorServiceImpl tokenValidatorService; | |
private static MockWebServer mockWebServer; | |
private AutoCloseable autoCloseable; | |
@BeforeEach | |
void setUp() { | |
mockWebServer = new MockWebServer(); | |
HttpUrl url = mockWebServer.url("/"); | |
WebClient.Builder mockedWebClient = WebClient.builder().baseUrl(url.toString()); | |
tokenValidatorService = new TokenValidatorServiceImpl(mockedWebClient); | |
ReflectionTestUtils.setField(tokenValidatorService, "fileAttRoute", String.format("localhost:%d", url.port())); | |
ReflectionTestUtils.setField(tokenValidatorService, "fileAttUrlPath", "/"); | |
autoCloseable = MockitoAnnotations.openMocks(this); | |
} | |
@AfterEach | |
void tearDown() throws Exception { | |
mockWebServer.close(); | |
autoCloseable.close(); | |
} | |
@Test | |
public void testValidateTokenInfo_TokenValid() { | |
// Given | |
String token = "Authorization Bearer 1234"; | |
// When | |
mockWebServer.enqueue(new MockResponse() | |
.setResponseCode(HttpStatus.OK.value()) | |
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | |
.setBody(getMockedTokenValidResponse())); | |
when(clientProperties.getAuthorizationHeader()).thenReturn("test"); | |
Mono<TokenInfo> result = tokenValidatorService.validateToken(token); | |
// Then | |
StepVerifier.create(result) | |
.expectNextMatches(tokenInfo -> { | |
boolean flag; | |
flag = tokenInfo.getFullname().equals("Bon Jovi"); | |
flag = flag && tokenInfo.getUser().equals("Feli"); | |
flag = flag && tokenInfo.getToken().equals("TOKEN"); | |
flag = flag && tokenInfo.getResponseCode() == 200; | |
flag = flag && tokenInfo.getUserGroups().equals("Admin"); | |
flag = flag && tokenInfo.getTokenStatus().equals("Active"); | |
return flag; | |
}) | |
.verifyComplete(); | |
} | |
@Test | |
public void testValidateTokenInfo_TokenInValid_TokenInfoNull() { | |
// Given | |
String token = "Authorization Bearer 1234"; | |
// When | |
mockWebServer.enqueue(new MockResponse() | |
.setResponseCode(HttpStatus.OK.value()) | |
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | |
.setBody("patience")); | |
when(clientProperties.getAuthorizationHeader()).thenReturn("test"); | |
Mono<TokenInfo> result = tokenValidatorService.validateToken(token); | |
// Then | |
StepVerifier.create(result).expectError(TokenNotFoundException.class).verify(); | |
} | |
@Test | |
public void testValidateTokenInfo_TokenInValid_TokenInfoUserIsEmpty() { | |
// Given | |
String token = "Authorization Bearer 1234"; | |
// When | |
mockWebServer.enqueue(new MockResponse() | |
.setResponseCode(HttpStatus.OK.value()) | |
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | |
.setBody(getMockedTokenInvalidResponseUserIsEmpty())); | |
when(clientProperties.getAuthorizationHeader()).thenReturn("test"); | |
Mono<TokenInfo> result = tokenValidatorService.validateToken(token); | |
// Then | |
StepVerifier.create(result).expectError(TokenNotFoundException.class).verify(); | |
} | |
@Test | |
public void testValidateTokenInfo_TokenInValid_TokenInfoHttpStatusIsEmpty() { | |
// Given | |
String token = "Authorization Bearer 1234"; | |
// When | |
mockWebServer.enqueue(new MockResponse() | |
.setResponseCode(HttpStatus.OK.value()) | |
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | |
.setBody(getMockedTokenInvalidResponseHttpStatusIsEmpty())); | |
when(clientProperties.getAuthorizationHeader()).thenReturn("test"); | |
Mono<TokenInfo> result = tokenValidatorService.validateToken(token); | |
// Then | |
StepVerifier.create(result).expectError(RoleNotFoundException.class).verify(); | |
} | |
@Test | |
public void testValidateTokenInfo_TokenInValid_TokenInfoHttpStatusIsNot200() { | |
// Given | |
String token = "Authorization Bearer 1234"; | |
// When | |
mockWebServer.enqueue(new MockResponse() | |
.setResponseCode(HttpStatus.OK.value()) | |
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | |
.setBody(getMockedTokenInvalidResponseHttpStatusIsNot200())); | |
when(clientProperties.getAuthorizationHeader()).thenReturn("test"); | |
Mono<TokenInfo> result = tokenValidatorService.validateToken(token); | |
// Then | |
StepVerifier.create(result).expectError(RoleNotFoundException.class).verify(); | |
} | |
@Test | |
public void testValidateTokenInfo_TokenInValid_TokenInfo_Resp200UserGroupNull() { | |
// Given | |
String token = "Authorization Bearer 1234"; | |
// When | |
mockWebServer.enqueue(new MockResponse() | |
.setResponseCode(HttpStatus.OK.value()) | |
.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) | |
.setBody(getMockedTokenInvalidResponseHttpStatusIs200UserGroupNull())); | |
when(clientProperties.getAuthorizationHeader()).thenReturn("test"); | |
Mono<TokenInfo> result = tokenValidatorService.validateToken(token); | |
// Then | |
StepVerifier.create(result).expectError(RoleNotFoundException.class).verify(); | |
} | |
private String getMockedTokenValidResponse() { | |
return "{\"responseCode\":200,\"user\":\"Feli\",\"userGroups\":\"Admin\",\"token\":\"TOKEN\"," | |
+ "\"tokenStatus\":\"Active\",\"fullname\":\"Bon Jovi\"}"; | |
} | |
private String getMockedTokenInvalidResponseUserIsEmpty() { | |
return "{\"token\":\"TOKEN\",\"tokenStatus\":\"Active\",\"fullname\":\"Bon Jovi\"}"; | |
} | |
private String getMockedTokenInvalidResponseHttpStatusIsEmpty() { | |
return "{\"token\":\"TOKEN\",\"tokenStatus\":\"Active\",\"user\":\"Feli\",\"fullname\":\"Bon Jovi\"}"; | |
} | |
private String getMockedTokenInvalidResponseHttpStatusIsNot200() { | |
return "{\"responseCode\":204,\"token\":\"TOKEN\",\"tokenStatus\":\"Active\"," | |
+ "\"user\":\"Feli\",\"fullname\":\"Bon Jovi\"}"; | |
} | |
private String getMockedTokenInvalidResponseHttpStatusIs200UserGroupNull() { | |
return "{\"responseCode\":200,\"token\":\"TOKEN\",\"tokenStatus\":\"Active\"," | |
+ "\"user\":\"Feli\",\"fullname\":\"Bon Jovi\"}"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment