Как создать модульные тесты для методов, аннотированных @Circuitbreaker - PullRequest
0 голосов
/ 30 марта 2020

Я реализовал resilience4j в своем проекте, используя стартер Spring Boot2 (https://resilience4j.readme.io/docs/getting-started-3).

Я аннотировал метод с помощью @CircuitBreaker, который использует http-клиент для вызова внешней службы и автоматический выключатель работает нормально - включая его запасной вариант.

Я хотел бы добавить для него модульные тесты, но когда я запускаю тест, пытаясь смоделировать запасной вариант, ничего не происходит - исключение выдается, но не обрабатывается механизм автоматического выключателя.

Я нашел несколько примеров, использующих его метрики, но в моем случае это бесполезно.

Есть мысли?

Вот фрагмент моего клиент:

@CircuitBreaker(name = "MY_CICUIT_BREAKER", fallbackMethod = "fallback")
    public ResponseEntity<String> search(String value) {

        ResponseEntity<String> responseEntity = restTemplate.exchange(
                searchURL,
                HttpMethod.GET,
                new HttpEntity(new HttpHeaders()),
                String.class,
                value);
    }

public ResponseEntity<String> fallback(String value, ResourceAccessException ex) {
        return "fallback executed";
    }

Ответы [ 2 ]

1 голос
/ 30 марта 2020

Вы не должны тестировать @CircuitBreaker в модульном тесте, так как в нем участвует более одного класса. Скорее используйте интеграционный тест.

0 голосов
/ 01 апреля 2020

Поскольку andres и pvpkiran упомянуто / объяснено, мне пришлось добавить интеграционный тест.

Вы можете добиться этого, просто добавив @ SpringBootTest аннотация к вашему тестовому классу, он будет bootstrap контейнером с пружинным контекстом.

Я также автоматически подключил CircuitBreakerRegistry для сброса автоматического выключателя перед каждым тестом, чтобы я мог гарантировать чистый тест. Для насмешек / шпионажа / проверки я использовал Mockito из весеннего загрузочного тестового стартера (spring-boot-starter-test).

Вот как мне удалось протестировать методы восстановления:

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = Application.class)
public class RestClientIntegrationTest {

    private final String SEARCH_VALUE = "1234567890";

    @MockBean( name = "myRealRestTemplateName")
    private RestTemplate restTemplate;

    @SpyBean
    private MyRestClient client;

    @Autowired
    private CircuitBreakerRegistry circuitBreakerRegistry;

    @BeforeEach
    public void setUp() {
        circuitBreakerRegistry.circuitBreaker("MY_CIRCUIT_BREAKER_NAME").reset();
    }

    @Test
    public void should_search_and_fallback_when_ResourceAccessException_is_thrown() {
        // prepare
        when(restTemplate.exchange(anyString(), eq(HttpMethod.GET), any(HttpEntity.class), eq(String.class), eq(SEARCH_VALUE)))
                .thenThrow(ResourceAccessException.class);

        String expectedResult = "expected result when fallback is called";

        // action
        String actualResult = client.search(SEARCH_VALUE);

        // assertion
        verify(client).fallback(eq(SEARCH_VALUE), any(ResourceAccessException.class));
        assertThat(actualResult, is(expectedResult));
    }

}

Я надеюсь, что нет ошибки компиляции, так как мне пришлось удалить некоторые несущественные вещи.

...