1
+ package dev .openfeature .sdk .hooks .logging ;
2
+
3
+ import static org .mockito .ArgumentMatchers .any ;
4
+ import static org .mockito .ArgumentMatchers .anyString ;
5
+ import static org .mockito .ArgumentMatchers .argThat ;
6
+ import static org .mockito .ArgumentMatchers .contains ;
7
+ import static org .mockito .Mockito .mock ;
8
+ import static org .mockito .Mockito .never ;
9
+ import static org .mockito .Mockito .verify ;
10
+ import static org .mockito .Mockito .when ;
11
+
12
+ import dev .openfeature .sdk .ClientMetadata ;
13
+ import dev .openfeature .sdk .ErrorCode ;
14
+ import dev .openfeature .sdk .EvaluationContext ;
15
+ import dev .openfeature .sdk .FlagEvaluationDetails ;
16
+ import dev .openfeature .sdk .FlagValueType ;
17
+ import dev .openfeature .sdk .HookContext ;
18
+ import dev .openfeature .sdk .ImmutableContext ;
19
+ import dev .openfeature .sdk .Metadata ;
20
+ import dev .openfeature .sdk .exceptions .GeneralError ;
21
+ import lombok .SneakyThrows ;
22
+ import org .junit .jupiter .api .BeforeEach ;
23
+ import org .junit .jupiter .api .Test ;
24
+ import org .simplify4u .slf4jmock .LoggerMock ;
25
+ import org .slf4j .Logger ;
26
+ import org .slf4j .spi .LoggingEventBuilder ;
27
+
28
+ public class LoggingHookTest {
29
+
30
+ private static final String FLAG_KEY = "some-key" ;
31
+ private static final String DEFAULT_VALUE = "default" ;
32
+ private static final String DOMAIN = "some-domain" ;
33
+ private static final String PROVIDER_NAME = "some-provider" ;
34
+ private static final String REASON = "some-reason" ;
35
+ private static final String VALUE = "some-value" ;
36
+ private static final String VARIANT = "some-variant" ;
37
+ private static final String ERROR_MESSAGE = "some fake error!" ;
38
+ private static final ErrorCode ERROR_CODE = ErrorCode .GENERAL ;
39
+
40
+ private HookContext <Object > hookContext ;
41
+ private LoggingEventBuilder mockBuilder ;
42
+ private Logger logger ;
43
+
44
+ @ BeforeEach
45
+ void each () {
46
+
47
+ // create a fake hook context
48
+ hookContext = HookContext .builder ().flagKey (FLAG_KEY ).defaultValue (DEFAULT_VALUE )
49
+ .clientMetadata (new ClientMetadata () {
50
+ @ Override
51
+ public String getDomain () {
52
+ return DOMAIN ;
53
+ }
54
+ }).providerMetadata (new Metadata () {
55
+ @ Override
56
+ public String getName () {
57
+ return PROVIDER_NAME ;
58
+ }
59
+ }).type (FlagValueType .BOOLEAN ).ctx (new ImmutableContext ()).build ();
60
+
61
+ // mock logging
62
+ logger = mock (Logger .class );
63
+ mockBuilder = mock (LoggingEventBuilder .class );
64
+ when (mockBuilder .addKeyValue (anyString (), anyString ())).thenReturn (mockBuilder );
65
+ when (logger .atInfo ()).thenReturn (mockBuilder );
66
+ when (logger .atError ()).thenReturn (mockBuilder );
67
+ LoggerMock .setMock (LoggingHook .class , logger );
68
+ }
69
+
70
+ @ SneakyThrows
71
+ @ Test
72
+ void beforeLogsAllPropsExceptEvaluationContext () {
73
+ LoggingHook hook = new LoggingHook ();
74
+ hook .before (hookContext , null );
75
+
76
+ verify (logger ).atInfo ();
77
+ verifyCommonProps (mockBuilder );
78
+ verify (mockBuilder , never ()).addKeyValue (anyString (), any (EvaluationContext .class ));
79
+ verify (mockBuilder ).log (argThat ((String s ) -> s .contains ("Before" )));
80
+ }
81
+
82
+ @ SneakyThrows
83
+ @ Test
84
+ void beforeLogsAllPropsAndEvaluationContext () {
85
+ LoggingHook hook = new LoggingHook (true );
86
+ hook .before (hookContext , null );
87
+
88
+ verify (logger ).atInfo ();
89
+ verifyCommonProps (mockBuilder );
90
+ verify (mockBuilder ).addKeyValue (contains (LoggingHook .EVALUATION_CONTEXT_KEY ), any (EvaluationContext .class ));
91
+ verify (mockBuilder ).log (argThat ((String s ) -> s .contains ("Before" )));
92
+ }
93
+
94
+ @ SneakyThrows
95
+ @ Test
96
+ void afterLogsAllPropsExceptEvaluationContext () {
97
+ LoggingHook hook = new LoggingHook ();
98
+ FlagEvaluationDetails <Object > details = FlagEvaluationDetails .builder ().reason (REASON ).variant (VARIANT ).value (VALUE ).build ();
99
+ hook .after (hookContext , details , null );
100
+
101
+ verify (logger ).atInfo ();
102
+ verifyAfterProps (mockBuilder );
103
+ verifyCommonProps (mockBuilder );
104
+ verify (mockBuilder , never ()).addKeyValue (anyString (), any (EvaluationContext .class ));
105
+ verify (mockBuilder ).log (argThat ((String s ) -> s .contains ("After" )));
106
+ }
107
+
108
+ @ SneakyThrows
109
+ @ Test
110
+ void afterLogsAllPropsAndEvaluationContext () {
111
+ LoggingHook hook = new LoggingHook (true );
112
+ FlagEvaluationDetails <Object > details = FlagEvaluationDetails .builder ().reason (REASON ).variant (VARIANT ).value (VALUE ).build ();
113
+ hook .after (hookContext , details , null );
114
+
115
+ verify (logger ).atInfo ();
116
+ verifyAfterProps (mockBuilder );
117
+ verifyCommonProps (mockBuilder );
118
+ verify (mockBuilder ).addKeyValue (contains (LoggingHook .EVALUATION_CONTEXT_KEY ), any (EvaluationContext .class ));
119
+ verify (mockBuilder ).log (argThat ((String s ) -> s .contains ("After" )));
120
+ }
121
+
122
+ @ SneakyThrows
123
+ @ Test
124
+ void errorLogsAllPropsExceptEvaluationContext () {
125
+ LoggingHook hook = new LoggingHook ();
126
+ GeneralError error = new GeneralError (ERROR_MESSAGE );
127
+ hook .error (hookContext , error , null );
128
+
129
+ verify (logger ).atError ();
130
+ verifyCommonProps (mockBuilder );
131
+ verifyErrorProps (mockBuilder );
132
+ verify (mockBuilder , never ()).addKeyValue (anyString (), any (EvaluationContext .class ));
133
+ verify (mockBuilder ).log (argThat ((String s ) -> s .contains ("Error" )), any (Exception .class ));
134
+ }
135
+
136
+ @ SneakyThrows
137
+ @ Test
138
+ void errorLogsAllPropsAndEvaluationContext () {
139
+ LoggingHook hook = new LoggingHook (true );
140
+ GeneralError error = new GeneralError (ERROR_MESSAGE );
141
+ hook .error (hookContext , error , null );
142
+
143
+ verify (logger ).atError ();
144
+ verifyCommonProps (mockBuilder );
145
+ verifyErrorProps (mockBuilder );
146
+ verify (mockBuilder ).addKeyValue (contains (LoggingHook .EVALUATION_CONTEXT_KEY ), any (EvaluationContext .class ));
147
+ verify (mockBuilder ).log (argThat ((String s ) -> s .contains ("Error" )), any (Exception .class ));
148
+ }
149
+
150
+ private void verifyCommonProps (LoggingEventBuilder mockBuilder ) {
151
+ verify (mockBuilder ).addKeyValue (LoggingHook .DOMAIN_KEY , DOMAIN );
152
+ verify (mockBuilder ).addKeyValue (LoggingHook .FLAG_KEY_KEY , FLAG_KEY );
153
+ verify (mockBuilder ).addKeyValue (LoggingHook .PROVIDER_NAME_KEY , PROVIDER_NAME );
154
+ verify (mockBuilder ).addKeyValue (LoggingHook .DEFAULT_VALUE_KEY , DEFAULT_VALUE );
155
+ }
156
+
157
+ private void verifyAfterProps (LoggingEventBuilder mockBuilder ) {
158
+ verify (mockBuilder ).addKeyValue (LoggingHook .REASON_KEY , REASON );
159
+ verify (mockBuilder ).addKeyValue (LoggingHook .VARIANT_KEY , VARIANT );
160
+ verify (mockBuilder ).addKeyValue (LoggingHook .VALUE_KEY , VALUE );
161
+ }
162
+
163
+ private void verifyErrorProps (LoggingEventBuilder mockBuilder ) {
164
+ verify (mockBuilder ).addKeyValue (LoggingHook .ERROR_CODE_KEY , ERROR_CODE );
165
+ verify (mockBuilder ).addKeyValue (LoggingHook .ERROR_MESSAGE_KEY , ERROR_MESSAGE );
166
+ }
167
+ }
0 commit comments