1
1
package cloud .eppo ;
2
2
3
- import static org .junit .jupiter .api .Assertions .assertNotNull ;
4
- import static org .junit . jupiter . api . Assertions . assertNull ;
3
+ import static org .junit .jupiter .api .Assertions .* ;
4
+ import static org .mockito . ArgumentMatchers . any ;
5
5
import static org .mockito .Mockito .mock ;
6
6
import static org .mockito .Mockito .when ;
7
7
12
12
import java .util .concurrent .CompletableFuture ;
13
13
import org .apache .commons .io .FileUtils ;
14
14
import org .junit .jupiter .api .Test ;
15
+ import org .mockito .Mockito ;
15
16
16
17
public class ConfigurationRequestorTest {
17
18
private final File initialFlagConfigFile =
@@ -21,7 +22,7 @@ public class ConfigurationRequestorTest {
21
22
22
23
@ Test
23
24
public void testInitialConfigurationFuture () throws IOException {
24
- IConfigurationStore configStore = new ConfigurationStore ();
25
+ IConfigurationStore configStore = Mockito . spy ( new ConfigurationStore () );
25
26
EppoHttpClient mockHttpClient = mock (EppoHttpClient .class );
26
27
27
28
ConfigurationRequestor requestor =
@@ -32,17 +33,20 @@ public void testInitialConfigurationFuture() throws IOException {
32
33
33
34
requestor .setInitialConfiguration (futureConfig );
34
35
35
- assertNull (configStore .getConfiguration ());
36
+ // verify config is empty to start
37
+ assertTrue (configStore .getConfiguration ().isEmpty ());
38
+ Mockito .verify (configStore , Mockito .times (0 )).saveConfiguration (any ());
36
39
37
40
futureConfig .complete (Configuration .builder (flagConfig , false ).build ());
38
41
39
- assertNotNull (configStore .getConfiguration ());
42
+ assertFalse (configStore .getConfiguration ().isEmpty ());
43
+ Mockito .verify (configStore , Mockito .times (1 )).saveConfiguration (any ());
40
44
assertNotNull (configStore .getConfiguration ().getFlag ("numeric_flag" ));
41
45
}
42
46
43
47
@ Test
44
48
public void testInitialConfigurationDoesntClobberFetch () throws IOException {
45
- IConfigurationStore configStore = new ConfigurationStore ();
49
+ IConfigurationStore configStore = Mockito . spy ( new ConfigurationStore () );
46
50
EppoHttpClient mockHttpClient = mock (EppoHttpClient .class );
47
51
48
52
ConfigurationRequestor requestor =
@@ -56,10 +60,11 @@ public void testInitialConfigurationDoesntClobberFetch() throws IOException {
56
60
57
61
when (mockHttpClient .getAsync ("/api/flag-config/v1/config" )).thenReturn (configFetchFuture );
58
62
59
- // Set initial config and verify that the config is still null as the inital config future has
60
- // not completed yet.
63
+ // Set initial config and verify that no config has been set yet.
61
64
requestor .setInitialConfiguration (initialConfigFuture );
62
- assertNull (configStore .getConfiguration ());
65
+
66
+ assertTrue (configStore .getConfiguration ().isEmpty ());
67
+ Mockito .verify (configStore , Mockito .times (0 )).saveConfiguration (any ());
63
68
64
69
// The initial config contains only one flag keyed `numeric_flag`. The fetch response has only
65
70
// one flag keyed
@@ -71,7 +76,8 @@ public void testInitialConfigurationDoesntClobberFetch() throws IOException {
71
76
configFetchFuture .complete (fetchedFlagConfig .getBytes (StandardCharsets .UTF_8 ));
72
77
initialConfigFuture .complete (new Configuration .Builder (flagConfig , false ).build ());
73
78
74
- assertNotNull (configStore .getConfiguration ());
79
+ assertFalse (configStore .getConfiguration ().isEmpty ());
80
+ Mockito .verify (configStore , Mockito .times (1 )).saveConfiguration (any ());
75
81
76
82
// `numeric_flag` is only in the cache which should have been ignored.
77
83
assertNull (configStore .getConfiguration ().getFlag ("numeric_flag" ));
@@ -82,7 +88,7 @@ public void testInitialConfigurationDoesntClobberFetch() throws IOException {
82
88
83
89
@ Test
84
90
public void testBrokenFetchDoesntClobberCache () throws IOException {
85
- IConfigurationStore configStore = new ConfigurationStore ();
91
+ IConfigurationStore configStore = Mockito . spy ( new ConfigurationStore () );
86
92
EppoHttpClient mockHttpClient = mock (EppoHttpClient .class );
87
93
88
94
ConfigurationRequestor requestor =
@@ -94,10 +100,11 @@ public void testBrokenFetchDoesntClobberCache() throws IOException {
94
100
95
101
when (mockHttpClient .getAsync ("/api/flag-config/v1/config" )).thenReturn (configFetchFuture );
96
102
97
- // Set initial config and verify that the config is still null as the inital config future has
98
- // not completed yet.
103
+ // Set initial config and verify that no config has been set yet.
99
104
requestor .setInitialConfiguration (initialConfigFuture );
100
- assertNull (configStore .getConfiguration ());
105
+
106
+ assertTrue (configStore .getConfiguration ().isEmpty ());
107
+ Mockito .verify (configStore , Mockito .times (0 )).saveConfiguration (any ());
101
108
102
109
requestor .fetchAndSaveFromRemoteAsync ();
103
110
@@ -107,7 +114,8 @@ public void testBrokenFetchDoesntClobberCache() throws IOException {
107
114
// Error out the fetch
108
115
configFetchFuture .completeExceptionally (new Exception ("Intentional exception" ));
109
116
110
- assertNotNull (configStore .getConfiguration ());
117
+ assertFalse (configStore .getConfiguration ().isEmpty ());
118
+ Mockito .verify (configStore , Mockito .times (1 )).saveConfiguration (any ());
111
119
112
120
// `numeric_flag` is only in the cache which should be available
113
121
assertNotNull (configStore .getConfiguration ().getFlag ("numeric_flag" ));
@@ -117,7 +125,7 @@ public void testBrokenFetchDoesntClobberCache() throws IOException {
117
125
118
126
@ Test
119
127
public void testCacheWritesAfterBrokenFetch () throws IOException {
120
- IConfigurationStore configStore = new ConfigurationStore ();
128
+ IConfigurationStore configStore = Mockito . spy ( new ConfigurationStore () );
121
129
EppoHttpClient mockHttpClient = mock (EppoHttpClient .class );
122
130
123
131
ConfigurationRequestor requestor =
@@ -129,20 +137,23 @@ public void testCacheWritesAfterBrokenFetch() throws IOException {
129
137
130
138
when (mockHttpClient .getAsync ("/api/flag-config/v1/config" )).thenReturn (configFetchFuture );
131
139
132
- // Set initial config and verify that the config is still null as the inital config future has
133
- // not completed yet.
140
+ // Set initial config and verify that no config has been set yet.
134
141
requestor .setInitialConfiguration (initialConfigFuture );
135
- assertNull (configStore . getConfiguration ());
142
+ Mockito . verify (configStore , Mockito . times ( 0 )). saveConfiguration ( any ());
136
143
137
- requestor .fetchAndSaveFromRemoteAsync ();
144
+ // default configuration is empty config.
145
+ assertTrue (configStore .getConfiguration ().isEmpty ());
138
146
139
- // Error out the fetch
147
+ // Fetch from remote with an error
148
+ requestor .fetchAndSaveFromRemoteAsync ();
140
149
configFetchFuture .completeExceptionally (new Exception ("Intentional exception" ));
141
150
142
151
// Resolve the initial config after the fetch throws an error.
143
152
initialConfigFuture .complete (new Configuration .Builder (flagConfig , false ).build ());
144
153
145
- assertNotNull (configStore .getConfiguration ());
154
+ // Verify that a configuration was saved by the requestor
155
+ Mockito .verify (configStore , Mockito .times (1 )).saveConfiguration (any ());
156
+ assertFalse (configStore .getConfiguration ().isEmpty ());
146
157
147
158
// `numeric_flag` is only in the cache which should be available
148
159
assertNotNull (configStore .getConfiguration ().getFlag ("numeric_flag" ));
0 commit comments