|
1 | 1 | package dev.openfeature.sdk;
|
2 | 2 |
|
| 3 | +import dev.openfeature.sdk.exceptions.FlagNotFoundError; |
3 | 4 | import dev.openfeature.sdk.fixtures.HookFixtures;
|
4 | 5 | import dev.openfeature.sdk.testutils.FeatureProviderTestUtils;
|
5 | 6 | import lombok.SneakyThrows;
|
|
19 | 20 | import static org.assertj.core.api.Assertions.assertThatCode;
|
20 | 21 | import static org.assertj.core.api.Assertions.fail;
|
21 | 22 | import static org.junit.jupiter.api.Assertions.assertEquals;
|
| 23 | +import static org.junit.jupiter.api.Assertions.assertInstanceOf; |
22 | 24 | import static org.junit.jupiter.api.Assertions.assertNotNull;
|
23 | 25 | import static org.junit.jupiter.api.Assertions.assertTrue;
|
24 | 26 | import static org.mockito.ArgumentMatchers.any;
|
25 | 27 | import static org.mockito.Mockito.doThrow;
|
26 | 28 | import static org.mockito.Mockito.inOrder;
|
27 | 29 | import static org.mockito.Mockito.mock;
|
| 30 | +import static org.mockito.Mockito.never; |
28 | 31 | import static org.mockito.Mockito.times;
|
29 | 32 | import static org.mockito.Mockito.verify;
|
30 | 33 | import static org.mockito.Mockito.when;
|
@@ -180,6 +183,40 @@ void emptyApiHooks() {
|
180 | 183 | verify(h, times(0)).error(any(), any(), any());
|
181 | 184 | }
|
182 | 185 |
|
| 186 | + |
| 187 | + @Test void error_hook_must_run_if_resolution_details_returns_an_error_code() { |
| 188 | + |
| 189 | + String errorMessage = "not found..."; |
| 190 | + |
| 191 | + EvaluationContext invocationCtx = new ImmutableContext(); |
| 192 | + Hook<Boolean> hook = mockBooleanHook(); |
| 193 | + FeatureProvider provider = mock(FeatureProvider.class); |
| 194 | + when(provider.getBooleanEvaluation(any(), any(), any())).thenReturn(ProviderEvaluation.<Boolean>builder() |
| 195 | + .errorCode(ErrorCode.FLAG_NOT_FOUND) |
| 196 | + .errorMessage(errorMessage) |
| 197 | + .build()); |
| 198 | + |
| 199 | + OpenFeatureAPI api = OpenFeatureAPI.getInstance(); |
| 200 | + FeatureProviderTestUtils.setFeatureProvider(provider); |
| 201 | + Client client = api.getClient(); |
| 202 | + client.getBooleanValue("key", false, invocationCtx, |
| 203 | + FlagEvaluationOptions.builder() |
| 204 | + .hook(hook) |
| 205 | + .build()); |
| 206 | + |
| 207 | + ArgumentCaptor<Exception> captor = ArgumentCaptor.forClass(Exception.class); |
| 208 | + |
| 209 | + verify(hook, times(1)).before(any(), any()); |
| 210 | + verify(hook, times(1)).error(any(), captor.capture(), any()); |
| 211 | + verify(hook, times(1)).finallyAfter(any(), any()); |
| 212 | + verify(hook, never()).after(any(),any(), any()); |
| 213 | + |
| 214 | + Exception exception = captor.getValue(); |
| 215 | + assertEquals(errorMessage, exception.getMessage()); |
| 216 | + assertInstanceOf(FlagNotFoundError.class, exception); |
| 217 | + } |
| 218 | + |
| 219 | + |
183 | 220 | @Specification(number="4.3.6", text="The after stage MUST run after flag resolution occurs. It accepts a hook context (required), flag evaluation details (required) and hook hints (optional). It has no return value.")
|
184 | 221 | @Specification(number="4.3.7", text="The error hook MUST run when errors are encountered in the before stage, the after stage or during flag resolution. It accepts hook context (required), exception representing what went wrong (required), and hook hints (optional). It has no return value.")
|
185 | 222 | @Specification(number="4.3.8", text="The finally hook MUST run after the before, after, and error stages. It accepts a hook context (required) and hook hints (optional). There is no return value.")
|
|
0 commit comments