Skip to content

Commit 4730807

Browse files
authored
BAEL-6369: Consume Emitted CircuitBreakerEvents in Resilience4j (#18797)
1 parent bd8644d commit 4730807

File tree

1 file changed

+266
-0
lines changed

1 file changed

+266
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,266 @@
1+
package com.baeldung.resilience4j.eventendpoints;
2+
3+
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
4+
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
5+
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
6+
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerEvent;
7+
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerOnErrorEvent;
8+
import io.github.resilience4j.circuitbreaker.event.CircuitBreakerOnSuccessEvent;
9+
import org.junit.jupiter.api.BeforeEach;
10+
import org.junit.jupiter.api.Test;
11+
import org.junit.jupiter.api.extension.ExtendWith;
12+
import org.mockito.ArgumentCaptor;
13+
import org.mockito.Captor;
14+
import org.mockito.Mock;
15+
import org.mockito.junit.jupiter.MockitoExtension;
16+
import org.slf4j.Logger;
17+
18+
import java.util.ArrayList;
19+
import java.util.List;
20+
21+
import static org.junit.jupiter.api.Assertions.*;
22+
23+
@ExtendWith(MockitoExtension.class)
24+
class CircuitBreakerEventConsumerUnitTest {
25+
26+
private CircuitBreaker circuitBreaker;
27+
private CircuitBreaker.EventPublisher eventPublisher;
28+
29+
@Mock
30+
private Logger mockLogger;
31+
32+
@Captor
33+
private ArgumentCaptor<String> logMessageCaptor;
34+
35+
@Captor
36+
private ArgumentCaptor<CircuitBreakerEvent> eventCaptor;
37+
38+
@BeforeEach
39+
void setUp() {
40+
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
41+
.failureRateThreshold(50)
42+
.slidingWindowSize(5)
43+
.build();
44+
45+
CircuitBreakerRegistry registry = CircuitBreakerRegistry.of(config);
46+
circuitBreaker = registry.circuitBreaker("testService");
47+
eventPublisher = circuitBreaker.getEventPublisher();
48+
}
49+
50+
@Test
51+
void givenSuccessEventConsumer_whenSuccessfulCallExecuted_thenSuccessEventIsPublished() {
52+
// Arrange
53+
List<CircuitBreakerEvent> capturedEvents = new ArrayList<>();
54+
eventPublisher.onSuccess(capturedEvents::add);
55+
56+
// Act
57+
String result = circuitBreaker.executeSupplier(() -> "success");
58+
59+
// Assert
60+
assertEquals(1, capturedEvents.size());
61+
assertInstanceOf(CircuitBreakerOnSuccessEvent.class, capturedEvents.get(0));
62+
assertEquals("success", result);
63+
}
64+
65+
@Test
66+
void givenErrorEventConsumer_whenFailingCallExecuted_thenErrorEventIsPublished() {
67+
// Arrange
68+
List<CircuitBreakerEvent> capturedEvents = new ArrayList<>();
69+
eventPublisher.onError(capturedEvents::add);
70+
71+
// Act & Assert
72+
RuntimeException exception = assertThrows(RuntimeException.class, () ->
73+
circuitBreaker.executeSupplier(() -> {
74+
throw new RuntimeException("Test error");
75+
})
76+
);
77+
78+
assertEquals(1, capturedEvents.size());
79+
assertInstanceOf(CircuitBreakerOnErrorEvent.class, capturedEvents.get(0));
80+
assertEquals("Test error", exception.getMessage());
81+
}
82+
83+
@Test
84+
void givenFailureRateExceededConsumer_whenConsumerRegistered_thenPublisherAcceptsRegistration() {
85+
// Arrange
86+
List<CircuitBreakerEvent> capturedEvents = new ArrayList<>();
87+
88+
// Act
89+
eventPublisher.onFailureRateExceeded(capturedEvents::add);
90+
91+
// Assert
92+
assertNotNull(eventPublisher);
93+
}
94+
95+
@Test
96+
void givenStateTransitionConsumer_whenConsumerRegistered_thenPublisherAcceptsRegistration() {
97+
// Arrange
98+
List<CircuitBreakerEvent> capturedEvents = new ArrayList<>();
99+
100+
// Act
101+
eventPublisher.onStateTransition(capturedEvents::add);
102+
103+
// Assert
104+
assertNotNull(eventPublisher);
105+
}
106+
107+
@Test
108+
void givenResetEventConsumer_whenConsumerRegistered_thenPublisherAcceptsRegistration() {
109+
// Arrange
110+
List<CircuitBreakerEvent> capturedEvents = new ArrayList<>();
111+
112+
// Act
113+
eventPublisher.onReset(capturedEvents::add);
114+
115+
// Assert
116+
assertNotNull(eventPublisher);
117+
}
118+
119+
@Test
120+
void givenMultipleEventConsumers_whenAllConsumersRegistered_thenAllRegistrationsAccepted() {
121+
// Arrange
122+
List<CircuitBreakerEvent> successEvents = new ArrayList<>();
123+
List<CircuitBreakerEvent> errorEvents = new ArrayList<>();
124+
List<CircuitBreakerEvent> stateTransitionEvents = new ArrayList<>();
125+
126+
// Act
127+
eventPublisher
128+
.onSuccess(successEvents::add)
129+
.onError(errorEvents::add)
130+
.onStateTransition(stateTransitionEvents::add);
131+
132+
// Assert
133+
assertNotNull(eventPublisher);
134+
}
135+
136+
@Test
137+
void givenNullConsumers_whenRegisteringEventConsumers_thenNoExceptionThrown() {
138+
// Arrange & Act & Assert
139+
assertDoesNotThrow(() -> {
140+
eventPublisher
141+
.onSuccess(null)
142+
.onError(null)
143+
.onIgnoredError(null);
144+
});
145+
146+
String result = circuitBreaker.executeSupplier(() -> "test");
147+
assertEquals("test", result);
148+
}
149+
150+
@Test
151+
void givenEventPublisher_whenChainingMultipleConsumerRegistrations_thenSamePublisherInstanceReturned() {
152+
// Arrange & Act
153+
CircuitBreaker.EventPublisher publisher = eventPublisher
154+
.onSuccess(event -> {
155+
})
156+
.onError(event -> {
157+
})
158+
.onIgnoredError(event -> {
159+
})
160+
.onCallNotPermitted(event -> {
161+
})
162+
.onFailureRateExceeded(event -> {
163+
})
164+
.onSlowCallRateExceeded(event -> {
165+
})
166+
.onStateTransition(event -> {
167+
})
168+
.onReset(event -> {
169+
});
170+
171+
// Assert
172+
assertSame(eventPublisher, publisher);
173+
}
174+
175+
@Test
176+
void givenMultipleEventConsumers_whenDifferentEventsTriggered_thenCorrespondingEventsAreCaptured() {
177+
// Arrange
178+
List<String> eventTypes = new ArrayList<>();
179+
180+
eventPublisher.onSuccess(event -> eventTypes.add("SUCCESS"));
181+
eventPublisher.onError(event -> eventTypes.add("ERROR"));
182+
eventPublisher.onStateTransition(event -> eventTypes.add("STATE_TRANSITION"));
183+
184+
// Act
185+
circuitBreaker.executeSupplier(() -> "success");
186+
try {
187+
circuitBreaker.executeSupplier(() -> {
188+
throw new RuntimeException();
189+
});
190+
} catch (Exception ignored) {
191+
}
192+
193+
// Assert
194+
assertTrue(eventTypes.contains("SUCCESS"));
195+
assertTrue(eventTypes.contains("ERROR"));
196+
}
197+
198+
@Test
199+
void givenCircuitBreakerInstance_whenGettingEventPublisher_thenNotNullPublisherReturned() {
200+
// Arrange & Act
201+
CircuitBreaker.EventPublisher publisher = circuitBreaker.getEventPublisher();
202+
203+
// Assert
204+
assertNotNull(publisher);
205+
assertSame(eventPublisher, publisher);
206+
}
207+
208+
@Test
209+
void givenSuccessEventConsumer_whenMultipleSuccessfulCallsExecuted_thenAllSuccessEventsArePublished() {
210+
// Arrange
211+
List<CircuitBreakerEvent> events = new ArrayList<>();
212+
eventPublisher.onSuccess(events::add);
213+
214+
// Act
215+
circuitBreaker.executeSupplier(() -> "first");
216+
circuitBreaker.executeSupplier(() -> "second");
217+
circuitBreaker.executeSupplier(() -> "third");
218+
219+
// Assert
220+
assertEquals(3, events.size());
221+
events.forEach(event ->
222+
assertInstanceOf(CircuitBreakerOnSuccessEvent.class, event)
223+
);
224+
}
225+
226+
@Test
227+
void givenCallNotPermittedConsumer_whenConsumerRegistered_thenPublisherAcceptsRegistration() {
228+
// Arrange
229+
List<CircuitBreakerEvent> capturedEvents = new ArrayList<>();
230+
231+
// Act
232+
eventPublisher.onCallNotPermitted(capturedEvents::add);
233+
234+
// Assert
235+
assertNotNull(eventPublisher);
236+
}
237+
238+
@Test
239+
void givenSlowCallRateExceededConsumer_whenConsumerRegistered_thenPublisherAcceptsRegistration() {
240+
// Arrange
241+
List<CircuitBreakerEvent> capturedEvents = new ArrayList<>();
242+
243+
// Act
244+
eventPublisher.onSlowCallRateExceeded(capturedEvents::add);
245+
246+
// Assert
247+
assertNotNull(eventPublisher);
248+
}
249+
250+
@Test
251+
void givenMultipleConsumersForSameEventType_whenEventPublished_thenAllConsumersReceiveEvent() {
252+
// Arrange
253+
List<String> consumerMessages = new ArrayList<>();
254+
255+
eventPublisher.onSuccess(event -> consumerMessages.add("consumer1"));
256+
eventPublisher.onSuccess(event -> consumerMessages.add("consumer2"));
257+
258+
// Act
259+
circuitBreaker.executeSupplier(() -> "test");
260+
261+
// Assert
262+
assertEquals(2, consumerMessages.size());
263+
assertTrue(consumerMessages.contains("consumer1"));
264+
assertTrue(consumerMessages.contains("consumer2"));
265+
}
266+
}

0 commit comments

Comments
 (0)