package org.zalando.actuate.failsafe; import net.jodah.failsafe.CircuitBreaker; import org.junit.Before; 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 org.springframework.test.context.junit4.SpringRunner; import org.springframework.web.client.DefaultResponseErrorHandler; import org.springframework.web.client.HttpClientErrorException; import javax.annotation.PostConstruct; import java.util.Map; import static net.jodah.failsafe.CircuitBreaker.State.CLOSED; import static net.jodah.failsafe.CircuitBreaker.State.HALF_OPEN; import static net.jodah.failsafe.CircuitBreaker.State.OPEN; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; import static org.springframework.http.HttpEntity.EMPTY; import static org.springframework.http.HttpMethod.GET; @RunWith(SpringRunner.class) @SpringBootTest(classes = SampleApplication.class, webEnvironment = RANDOM_PORT) public class CircuitBreakersEndpointTest { @Autowired private TestRestTemplate http; @PostConstruct public void configure() { this.http.getRestTemplate().setErrorHandler(new DefaultResponseErrorHandler()); } @Before public void before() { write("test", CLOSED); } @Test public void shouldReadAll() { final Map<String, CircuitBreakerView> breakers = readAll().getCircuitBreakers(); assertEquals(2, breakers.size()); assertTrue(breakers.containsKey("test")); assertTrue(breakers.containsKey("delay")); final CircuitBreakerView view = breakers.get("test"); assertEquals(CLOSED, view.getState()); } @Test public void shouldReadOne() { final CircuitBreakerView view = readOne("test"); assertNotNull(view); assertEquals(CLOSED, view.getState()); } @Test(expected = HttpClientErrorException.class) public void shouldReadUnknown() { readOne("unknown"); } @Test public void shouldOpen() { verifyTransitionTo(OPEN); } @Test public void shouldHalfOpen() { verifyTransitionTo(HALF_OPEN); } @Test public void shouldClose() { write("test", OPEN); // so we have an actual state change, since closed is the default verifyTransitionTo(CLOSED); } @Test public void shouldWriteUnknown() { assertNull(write("unknown", OPEN)); } private void verifyTransitionTo(final CircuitBreaker.State state) { final CircuitBreakerView written = write("test", state); final CircuitBreakerView read = readOne("test"); assertEquals(read, written); assertEquals(read.getState(), state); } private Container readAll() { return http.exchange("/actuator/circuit-breakers", GET, EMPTY, Container.class).getBody(); } private CircuitBreakerView readOne(final String name) { return http.getForObject("/actuator/circuit-breakers/{name}", CircuitBreakerView.class, name); } private CircuitBreakerView write(final String test, final CircuitBreaker.State state) { return http.postForObject("/actuator/circuit-breakers/{name}", new CircuitBreakerView(state), CircuitBreakerView.class, test); } }