Files
spring-boot-rest/spring-boot-modules/spring-boot-libraries-2/src/test/java/com/baeldung/resilientapp/ResilientAppControllerUnitTest.java
2022-10-16 21:33:41 -05:00

135 lines
5.5 KiB
Java

package com.baeldung.resilientapp;
import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
import static com.github.tomakehurst.wiremock.client.WireMock.ok;
import static com.github.tomakehurst.wiremock.client.WireMock.serverError;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.springframework.http.HttpStatus.BANDWIDTH_LIMIT_EXCEEDED;
import static org.springframework.http.HttpStatus.OK;
import static org.springframework.http.HttpStatus.TOO_MANY_REQUESTS;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.IntStream;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
import com.github.tomakehurst.wiremock.junit5.WireMockExtension;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class ResilientAppControllerUnitTest {
@RegisterExtension
static WireMockExtension EXTERNAL_SERVICE = WireMockExtension.newInstance()
.options(WireMockConfiguration.wireMockConfig()
.port(9090))
.build();
@Autowired
private TestRestTemplate restTemplate;
@Test
public void testCircuitBreaker() {
EXTERNAL_SERVICE.stubFor(WireMock.get("/api/external")
.willReturn(serverError()));
IntStream.rangeClosed(1, 5)
.forEach(i -> {
ResponseEntity<String> response = restTemplate.getForEntity("/api/circuit-breaker", String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
});
IntStream.rangeClosed(1, 5)
.forEach(i -> {
ResponseEntity<String> response = restTemplate.getForEntity("/api/circuit-breaker", String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.SERVICE_UNAVAILABLE);
});
EXTERNAL_SERVICE.verify(5, getRequestedFor(urlEqualTo("/api/external")));
}
@Test
public void testRetry() {
EXTERNAL_SERVICE.stubFor(WireMock.get("/api/external")
.willReturn(ok()));
ResponseEntity<String> response1 = restTemplate.getForEntity("/api/retry", String.class);
EXTERNAL_SERVICE.verify(1, getRequestedFor(urlEqualTo("/api/external")));
EXTERNAL_SERVICE.resetRequests();
EXTERNAL_SERVICE.stubFor(WireMock.get("/api/external")
.willReturn(serverError()));
ResponseEntity<String> response2 = restTemplate.getForEntity("/api/retry", String.class);
Assert.assertEquals(response2.getBody(), "all retries have exhausted");
EXTERNAL_SERVICE.verify(3, getRequestedFor(urlEqualTo("/api/external")));
}
@Test
public void testBulkhead() {
EXTERNAL_SERVICE.stubFor(WireMock.get("/api/external")
.willReturn(ok()));
Map<Integer, Integer> responseStatusCount = new ConcurrentHashMap<>();
IntStream.rangeClosed(1, 5)
.parallel()
.forEach(i -> {
ResponseEntity<String> response = restTemplate.getForEntity("/api/bulkhead", String.class);
int statusCode = response.getStatusCodeValue();
responseStatusCount.put(statusCode, responseStatusCount.getOrDefault(statusCode, 0) + 1);
});
assertEquals(2, responseStatusCount.keySet()
.size());
assertTrue(responseStatusCount.containsKey(BANDWIDTH_LIMIT_EXCEEDED.value()));
assertTrue(responseStatusCount.containsKey(OK.value()));
EXTERNAL_SERVICE.verify(3, getRequestedFor(urlEqualTo("/api/external")));
}
@Test
public void testTimeLimiter() {
EXTERNAL_SERVICE.stubFor(WireMock.get("/api/external")
.willReturn(ok()));
ResponseEntity<String> response = restTemplate.getForEntity("/api/time-limiter", String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.REQUEST_TIMEOUT);
EXTERNAL_SERVICE.verify(1, getRequestedFor(urlEqualTo("/api/external")));
}
@Test
public void testRatelimiter() {
EXTERNAL_SERVICE.stubFor(WireMock.get("/api/external")
.willReturn(ok()));
Map<Integer, Integer> responseStatusCount = new ConcurrentHashMap<>();
IntStream.rangeClosed(1, 50)
.parallel()
.forEach(i -> {
ResponseEntity<String> response = restTemplate.getForEntity("/api/rate-limiter", String.class);
int statusCode = response.getStatusCodeValue();
responseStatusCount.put(statusCode, responseStatusCount.getOrDefault(statusCode, 0) + 1);
});
assertEquals(2, responseStatusCount.keySet()
.size());
assertTrue(responseStatusCount.containsKey(TOO_MANY_REQUESTS.value()));
assertTrue(responseStatusCount.containsKey(OK.value()));
EXTERNAL_SERVICE.verify(5, getRequestedFor(urlEqualTo("/api/external")));
}
}