diff --git a/build.gradle b/build.gradle index a857112..5657287 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ buildscript { ext { - springBootVersion = '2.5.2' + springBootVersion = '2.5.3' } repositories { mavenCentral() @@ -15,7 +15,7 @@ apply plugin: 'eclipse' apply plugin: 'org.springframework.boot' apply plugin: 'io.spring.dependency-management' -sourceCompatibility = 1.8 +sourceCompatibility = 11 repositories { mavenCentral() diff --git a/src/main/java/io/github/robwin/controller/BackendBController.java b/src/main/java/io/github/robwin/controller/BackendBController.java index 7f241de..80ce927 100644 --- a/src/main/java/io/github/robwin/controller/BackendBController.java +++ b/src/main/java/io/github/robwin/controller/BackendBController.java @@ -96,9 +96,14 @@ public Mono monoFailure() { return execute(businessBService.monoFailure()); } + @GetMapping("monoTimeout") + public Mono monoTimeout(){ + return executeWithFallback(businessBService.monoTimeout(), this::monoFallback); + } + @GetMapping("fluxSuccess") public Flux fluxSuccess(){ - return execute(businessBService.fluxFailure()); + return execute(businessBService.fluxSuccess()); } @GetMapping("fluxFailure") @@ -106,11 +111,6 @@ public Flux fluxFailure(){ return execute(businessBService.fluxFailure()); } - @GetMapping("monoTimeout") - public Mono monoTimeout(){ - return executeWithFallback(businessBService.monoTimeout(), this::monoFallback); - } - @GetMapping("fluxTimeout") public Flux fluxTimeout(){ return executeWithFallback(businessBService.fluxTimeout(), this::fluxFallback); diff --git a/src/main/java/io/github/robwin/controller/BackendCController.java b/src/main/java/io/github/robwin/controller/BackendCController.java index 120d7c6..9ef134b 100644 --- a/src/main/java/io/github/robwin/controller/BackendCController.java +++ b/src/main/java/io/github/robwin/controller/BackendCController.java @@ -50,6 +50,11 @@ public Mono monoFailure(){ return businessCService.monoFailure(); } + @GetMapping("monoTimeout") + public Mono monoTimeout(){ + return businessCService.monoTimeout(); + } + @GetMapping("fluxSuccess") public Flux fluxSuccess(){ return businessCService.fluxSuccess(); @@ -60,11 +65,6 @@ public Flux fluxFailure(){ return businessCService.fluxFailure(); } - @GetMapping("monoTimeout") - public Mono monoTimeout(){ - return businessCService.monoTimeout(); - } - @GetMapping("fluxTimeout") public Flux fluxTimeout(){ return businessCService.fluxTimeout(); diff --git a/src/test/java/io/github/robwin/AbstractIntegrationTest.java b/src/test/java/io/github/robwin/AbstractIntegrationTest.java index e70eaa9..3015a6e 100644 --- a/src/test/java/io/github/robwin/AbstractIntegrationTest.java +++ b/src/test/java/io/github/robwin/AbstractIntegrationTest.java @@ -1,49 +1,47 @@ package io.github.robwin; -import org.junit.Before; -import org.junit.runner.RunWith; + +import io.github.resilience4j.circuitbreaker.CircuitBreaker; +import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.web.client.TestRestTemplate; -import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.reactive.server.WebTestClient; -import io.github.resilience4j.circuitbreaker.CircuitBreaker; -import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry; +import org.junit.jupiter.api.BeforeAll; + -@RunWith(SpringRunner.class) @AutoConfigureWebTestClient -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, - classes = Application.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = Application.class) public abstract class AbstractIntegrationTest { - protected static final String BACKEND_A = "backendA"; - protected static final String BACKEND_B = "backendB"; + protected static final String BACKEND_A = "backendA"; + protected static final String BACKEND_B = "backendB"; - @Autowired - protected CircuitBreakerRegistry circuitBreakerRegistry; + @Autowired + protected CircuitBreakerRegistry circuitBreakerRegistry; - @Autowired - protected TestRestTemplate restTemplate; + @Autowired + protected TestRestTemplate restTemplate; - @Autowired - protected WebTestClient webClient; + @Autowired + protected WebTestClient webClient; - @Before - public void setup() { - transitionToClosedState(BACKEND_A); - transitionToClosedState(BACKEND_B); - } + @BeforeAll + public void setup() { + transitionToClosedState(BACKEND_A); + transitionToClosedState(BACKEND_B); + } - protected void transitionToOpenState(String circuitBreakerName) { - CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker(circuitBreakerName); - circuitBreaker.transitionToOpenState(); - } + protected void transitionToOpenState(String circuitBreakerName) { + CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker(circuitBreakerName); + circuitBreaker.transitionToOpenState(); + } - protected void transitionToClosedState(String circuitBreakerName) { - CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker(circuitBreakerName); - circuitBreaker.transitionToClosedState(); - } + protected void transitionToClosedState(String circuitBreakerName) { + CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker(circuitBreakerName); + circuitBreaker.transitionToClosedState(); + } } diff --git a/src/test/java/io/github/robwin/CircuitBreakerTest.java b/src/test/java/io/github/robwin/CircuitBreakerTest.java index ee2b262..92f2559 100644 --- a/src/test/java/io/github/robwin/CircuitBreakerTest.java +++ b/src/test/java/io/github/robwin/CircuitBreakerTest.java @@ -2,64 +2,62 @@ import static io.github.resilience4j.circuitbreaker.CircuitBreaker.State; import static org.assertj.core.api.Assertions.assertThat; - -import org.junit.Test; +import static org.assertj.core.api.Assertions.fail; +import io.vavr.collection.Stream; +import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import io.vavr.collection.Stream; - public class CircuitBreakerTest extends AbstractCircuitBreakerTest { - @Test - public void shouldOpenBackendACircuitBreaker() { - // When - Stream.rangeClosed(1,2).forEach((count) -> produceFailure(BACKEND_A)); - - // Then - checkHealthStatus(BACKEND_A, State.OPEN); - } - - @Test - public void shouldCloseBackendACircuitBreaker() { - transitionToOpenState(BACKEND_A); - circuitBreakerRegistry.circuitBreaker(BACKEND_A).transitionToHalfOpenState(); - - // When - Stream.rangeClosed(1,3).forEach((count) -> produceSuccess(BACKEND_A)); - - // Then - checkHealthStatus(BACKEND_A, State.CLOSED); - } - - @Test - public void shouldOpenBackendBCircuitBreaker() { - // When - Stream.rangeClosed(1,4).forEach((count) -> produceFailure(BACKEND_B)); - - // Then - checkHealthStatus(BACKEND_B, State.OPEN); - } - - @Test - public void shouldCloseBackendBCircuitBreaker() { - transitionToOpenState(BACKEND_B); - circuitBreakerRegistry.circuitBreaker(BACKEND_B).transitionToHalfOpenState(); - - // When - Stream.rangeClosed(1,3).forEach((count) -> produceSuccess(BACKEND_B)); - - // Then - checkHealthStatus(BACKEND_B, State.CLOSED); - } - - private void produceFailure(String backend) { - ResponseEntity response = restTemplate.getForEntity("/" + backend + "/failure", String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - } - - private void produceSuccess(String backend) { - ResponseEntity response = restTemplate.getForEntity("/" + backend + "/success", String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - } + @Test + public void shouldOpenBackendACircuitBreaker() { + // When + Stream.rangeClosed(1, 2).forEach((count) -> produceFailure(BACKEND_A)); + // Then + checkHealthStatus(BACKEND_A, State.OPEN); + } + + @Test + public void shouldCloseBackendACircuitBreaker() { + transitionToOpenState(BACKEND_A); + circuitBreakerRegistry.circuitBreaker(BACKEND_A).transitionToHalfOpenState(); + + // When + Stream.rangeClosed(1, 3).forEach((count) -> produceSuccess(BACKEND_A)); + + // Then + checkHealthStatus(BACKEND_A, State.CLOSED); + } + + @Test + public void shouldOpenBackendBCircuitBreaker() { + // When + Stream.rangeClosed(1, 4).forEach((count) -> produceFailure(BACKEND_B)); + + // Then + checkHealthStatus(BACKEND_B, State.OPEN); + } + + @Test + public void shouldCloseBackendBCircuitBreaker() { + transitionToOpenState(BACKEND_B); + circuitBreakerRegistry.circuitBreaker(BACKEND_B).transitionToHalfOpenState(); + + // When + Stream.rangeClosed(1, 3).forEach((count) -> produceSuccess(BACKEND_B)); + + // Then + checkHealthStatus(BACKEND_B, State.CLOSED); + } + + private void produceFailure(String backend) { + ResponseEntity response = restTemplate.getForEntity("/" + backend + "/failure", String.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + } + + private void produceSuccess(String backend) { + ResponseEntity response = restTemplate.getForEntity("/" + backend + "/success", String.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } } diff --git a/src/test/java/io/github/robwin/FutureCircuitBreakerTest.java b/src/test/java/io/github/robwin/FutureCircuitBreakerTest.java index 2613fee..19dd21b 100644 --- a/src/test/java/io/github/robwin/FutureCircuitBreakerTest.java +++ b/src/test/java/io/github/robwin/FutureCircuitBreakerTest.java @@ -3,7 +3,7 @@ import static io.github.resilience4j.circuitbreaker.CircuitBreaker.State; import static org.assertj.core.api.Assertions.assertThat; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/src/test/java/io/github/robwin/FutureRetryTest.java b/src/test/java/io/github/robwin/FutureRetryTest.java index a537809..29bd4c1 100644 --- a/src/test/java/io/github/robwin/FutureRetryTest.java +++ b/src/test/java/io/github/robwin/FutureRetryTest.java @@ -2,9 +2,7 @@ import static org.assertj.core.api.Assertions.assertThat; -import java.util.Arrays; - -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; diff --git a/src/test/java/io/github/robwin/ReactiveCircuitBreakerTest.java b/src/test/java/io/github/robwin/ReactiveCircuitBreakerTest.java index f9ea412..144b0cb 100644 --- a/src/test/java/io/github/robwin/ReactiveCircuitBreakerTest.java +++ b/src/test/java/io/github/robwin/ReactiveCircuitBreakerTest.java @@ -2,9 +2,8 @@ import static io.github.resilience4j.circuitbreaker.CircuitBreaker.State; -import org.junit.Test; - import io.vavr.collection.Stream; +import org.junit.jupiter.api.Test; public class ReactiveCircuitBreakerTest extends AbstractCircuitBreakerTest { diff --git a/src/test/java/io/github/robwin/ReactiveRetryTest.java b/src/test/java/io/github/robwin/ReactiveRetryTest.java index fe546aa..383168f 100644 --- a/src/test/java/io/github/robwin/ReactiveRetryTest.java +++ b/src/test/java/io/github/robwin/ReactiveRetryTest.java @@ -1,62 +1,56 @@ package io.github.robwin; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; public class ReactiveRetryTest extends AbstractRetryTest { - @Test - public void backendAshouldRetryThreeTimes() { - // When - float currentCount = getCurrentCount(FAILED_WITH_RETRY, BACKEND_A); - produceFailure(BACKEND_A); - - checkMetrics(FAILED_WITH_RETRY, BACKEND_A, currentCount + 1); - } - - @Test - public void backendBshouldRetryThreeTimes() { - // When - float currentCount = getCurrentCount(FAILED_WITH_RETRY, BACKEND_B); - produceFailure(BACKEND_B); - - checkMetrics(FAILED_WITH_RETRY, BACKEND_B, currentCount + 1); - } - - @Test - public void backendAshouldSucceedWithoutRetry() { - float currentCount = getCurrentCount(SUCCESS_WITHOUT_RETRY, BACKEND_A); - produceSuccess(BACKEND_A); - - checkMetrics(SUCCESS_WITHOUT_RETRY, BACKEND_A, currentCount + 1); - } - - @Test - public void backendBshouldSucceedWithoutRetry() { - float currentCount = getCurrentCount(SUCCESS_WITHOUT_RETRY, BACKEND_B); - produceSuccess(BACKEND_B); - - checkMetrics(SUCCESS_WITHOUT_RETRY, BACKEND_B, currentCount + 1); - } - - private void produceFailure(String backend) { - ResponseEntity response = restTemplate.getForEntity("/" + backend + "/monoFailure", String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - } - - private void produceSuccess(String backend) { - ResponseEntity response = restTemplate.getForEntity("/" + backend + "/monoSuccess", String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - } + @Test + public void backendAshouldRetryThreeTimes() { + // When + float currentCount = getCurrentCount(FAILED_WITH_RETRY, BACKEND_A); + produceFailure(BACKEND_A); + + checkMetrics(FAILED_WITH_RETRY, BACKEND_A, currentCount + 1); + } + + @Test + public void backendBshouldRetryThreeTimes() { + // When + float currentCount = getCurrentCount(FAILED_WITH_RETRY, BACKEND_B); + produceFailure(BACKEND_B); + + checkMetrics(FAILED_WITH_RETRY, BACKEND_B, currentCount + 1); + } + + @Test + public void backendAshouldSucceedWithoutRetry() { + float currentCount = getCurrentCount(SUCCESS_WITHOUT_RETRY, BACKEND_A); + produceSuccess(BACKEND_A); + + checkMetrics(SUCCESS_WITHOUT_RETRY, BACKEND_A, currentCount + 1); + } + + @Test + public void backendBshouldSucceedWithoutRetry() { + float currentCount = getCurrentCount(SUCCESS_WITHOUT_RETRY, BACKEND_B); + produceSuccess(BACKEND_B); + + checkMetrics(SUCCESS_WITHOUT_RETRY, BACKEND_B, currentCount + 1); + } + + private void produceFailure(String backend) { + ResponseEntity response = restTemplate.getForEntity("/" + backend + "/monoFailure", String.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + } + + private void produceSuccess(String backend) { + ResponseEntity response = restTemplate.getForEntity("/" + backend + "/monoSuccess", String.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } } diff --git a/src/test/java/io/github/robwin/RetryTest.java b/src/test/java/io/github/robwin/RetryTest.java index 186aadb..be3fd91 100644 --- a/src/test/java/io/github/robwin/RetryTest.java +++ b/src/test/java/io/github/robwin/RetryTest.java @@ -1,61 +1,54 @@ package io.github.robwin; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.web.client.TestRestTemplate; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.jupiter.api.Test; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.junit4.SpringRunner; - -import static org.assertj.core.api.Assertions.assertThat; public class RetryTest extends AbstractRetryTest { - @Test - public void backendAshouldRetryThreeTimes() { - // When - float currentCount = getCurrentCount(FAILED_WITH_RETRY, BACKEND_A); - produceFailure(BACKEND_A); - - checkMetrics(FAILED_WITH_RETRY, BACKEND_A, currentCount + 1); - } - - @Test - public void backendBshouldRetryThreeTimes() { - // When - float currentCount = getCurrentCount(FAILED_WITH_RETRY, BACKEND_B); - produceFailure(BACKEND_B); - - checkMetrics(FAILED_WITH_RETRY, BACKEND_B, currentCount + 1); - } - - @Test - public void backendAshouldSucceedWithoutRetry() { - float currentCount = getCurrentCount(SUCCESS_WITHOUT_RETRY, BACKEND_A); - produceSuccess(BACKEND_A); - - checkMetrics(SUCCESS_WITHOUT_RETRY, BACKEND_A, currentCount + 1); - } - - @Test - public void backendBshouldSucceedWithoutRetry() { - float currentCount = getCurrentCount(SUCCESS_WITHOUT_RETRY, BACKEND_B); - produceSuccess(BACKEND_B); - - checkMetrics(SUCCESS_WITHOUT_RETRY, BACKEND_B, currentCount + 1); - } - - private void produceFailure(String backend) { - ResponseEntity response = restTemplate.getForEntity("/" + backend + "/failure", String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - } - - private void produceSuccess(String backend) { - ResponseEntity response = restTemplate.getForEntity("/" + backend + "/success", String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - } + @Test + public void backendAshouldRetryThreeTimes() { + // When + float currentCount = getCurrentCount(FAILED_WITH_RETRY, BACKEND_A); + produceFailure(BACKEND_A); + + checkMetrics(FAILED_WITH_RETRY, BACKEND_A, currentCount + 1); + } + + @Test + public void backendBshouldRetryThreeTimes() { + // When + float currentCount = getCurrentCount(FAILED_WITH_RETRY, BACKEND_B); + produceFailure(BACKEND_B); + + checkMetrics(FAILED_WITH_RETRY, BACKEND_B, currentCount + 1); + } + + @Test + public void backendAshouldSucceedWithoutRetry() { + float currentCount = getCurrentCount(SUCCESS_WITHOUT_RETRY, BACKEND_A); + produceSuccess(BACKEND_A); + + checkMetrics(SUCCESS_WITHOUT_RETRY, BACKEND_A, currentCount + 1); + } + + @Test + public void backendBshouldSucceedWithoutRetry() { + float currentCount = getCurrentCount(SUCCESS_WITHOUT_RETRY, BACKEND_B); + produceSuccess(BACKEND_B); + + checkMetrics(SUCCESS_WITHOUT_RETRY, BACKEND_B, currentCount + 1); + } + + private void produceFailure(String backend) { + ResponseEntity response = restTemplate.getForEntity("/" + backend + "/failure", String.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + } + + private void produceSuccess(String backend) { + ResponseEntity response = restTemplate.getForEntity("/" + backend + "/success", String.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + } }