2020
2121import com .fasterxml .jackson .databind .ObjectMapper ;
2222import java .io .IOException ;
23+ import java .util .HashMap ;
2324import java .util .Map ;
25+ import lombok .experimental .SuperBuilder ;
2426import org .junit .jupiter .api .Test ;
2527import org .junit .jupiter .params .ParameterizedTest ;
2628import org .junit .jupiter .params .provider .CsvSource ;
@@ -43,7 +45,7 @@ void givenEnvVariables_whenReplaceWithEnv_thenReplaceCorrectlyVars(
4345 Map .of (
4446 "USER" , "John" ,
4547 "PATH" , "/usr/bin" );
46- resolver = EnvVarResolver .of ( envVariables );
48+ resolver = EnvVarResolver .builder (). envVars ( envVariables ). build ( );
4749 var result = resolver .resolve (command );
4850 assertThat (result ).isEqualTo (expected );
4951 }
@@ -57,7 +59,7 @@ void givenEnvVariables_whenReplaceWithEnv_thenReplaceCorrectlyVars(
5759 })
5860 void givenMissingEnvVariables_whenResolveEnv_Vars_thenThrowException (String command ) {
5961 Map <String , String > envVariables = Map .of ();
60- resolver = EnvVarResolver .of ( envVariables ); // Empty map to simulate missing variables
62+ resolver = EnvVarResolver .builder (). envVars ( envVariables ). build ();
6163 assertThatThrownBy (() -> resolver .resolve (command ))
6264 .isInstanceOf (IllegalStateException .class )
6365 .hasMessageStartingWith (
@@ -76,7 +78,7 @@ void givenSimilarEnvVariableNames_whenResolveEnv_Vars_thenPartialMatchDoesNotOcc
7678 Map .of (
7779 "USER" , "John" ,
7880 "NAME" , "exists" );
79- resolver = EnvVarResolver .of ( envVariables );
81+ resolver = EnvVarResolver .builder (). envVars ( envVariables ). build ( );
8082 assertThatThrownBy (() -> resolver .resolve (command ))
8183 .isInstanceOf (IllegalStateException .class )
8284 .hasMessage (
@@ -105,7 +107,7 @@ void givenDefaultEnvValues_whenResolve_thenFallbackOrUseEnvValue(
105107 Map .of (
106108 "USER" , "John" ,
107109 "PATH" , "/usr/bin" );
108- resolver = EnvVarResolver .of ( envVariables );
110+ resolver = EnvVarResolver .builder (). envVars ( envVariables ). build ( );
109111 var result = resolver .resolve (command );
110112 assertThat (result ).isEqualTo (expected );
111113 }
@@ -120,7 +122,7 @@ void givenDefaultEnvValues_whenResolve_thenFallbackOrUseEnvValue(
120122 })
121123 void givenMissingEnvWithoutDefault_whenResolve_thenThrowException (String command ) {
122124 Map <String , String > envVariables = Map .of ("A" , "something" );
123- resolver = EnvVarResolver .of ( envVariables );
125+ resolver = EnvVarResolver .builder (). envVars ( envVariables ). build ( );
124126 assertThatThrownBy (() -> resolver .resolve (command ))
125127 .isInstanceOf (IllegalStateException .class )
126128 .hasMessageContaining ("referenced, but not found" );
@@ -136,22 +138,36 @@ void givenMissingEnvWithoutDefault_whenResolve_thenThrowException(String command
136138 })
137139 void givenFallbackWithColons_whenResolve_thenParseCorrectly (String command , String expected ) {
138140 Map <String , String > envVariables = Map .of (); // No TOKEN set
139- resolver = EnvVarResolver .of ( envVariables );
141+ resolver = EnvVarResolver .builder (). envVars ( envVariables ). build ( );
140142 var result = resolver .resolve (command );
141143 assertThat (result ).isEqualTo (expected );
142144 }
143145
146+ @ ParameterizedTest
147+ @ CsvSource ({
148+ "'${{SECRET}}', '${{SECRET}}'" ,
149+ "'Token=${{SECRET}}', 'Token=${{SECRET}}'" ,
150+ "'Host=${HOST}, password=${{DB_PASSWORD}}', 'Host=db.example.com, password=${{DB_PASSWORD}}'"
151+ })
152+ void givenSecretEnvTemplate_whenResolve_thenLeaveUnchanged (String command , String expected ) {
153+ resolver = EnvVarResolver .builder ().envVars (Map .of ("HOST" , "db.example.com" )).build ();
154+
155+ var result = resolver .resolve (command );
156+
157+ assertThat (result ).isEqualTo (expected );
158+ }
159+
144160 @ Test
145161 void givenNullOrBlankSource_whenResolve_thenReturnSource () {
146- resolver = EnvVarResolver .of ( Map .of ());
162+ resolver = EnvVarResolver .builder (). envVars ( Map .of ()). build ( );
147163
148164 assertThat (resolver .resolve (null )).isNull ();
149165 assertThat (resolver .resolve (" " )).isEqualTo (" " );
150166 }
151167
152168 @ Test
153169 void givenNonStrictResolver_whenMissingEnvVariables_thenLeavesPlaceholdersUnresolved () {
154- resolver = EnvVarResolver .of ( Map .of ("USER" , "John" ), false );
170+ resolver = EnvVarResolver .builder (). envVars ( Map .of ("USER" , "John" )). strict ( false ). build ( );
155171
156172 var result = resolver .resolve ("Hello ${USER}, ${MISSING}!" );
157173
@@ -161,10 +177,13 @@ void givenNonStrictResolver_whenMissingEnvVariables_thenLeavesPlaceholdersUnreso
161177 @ Test
162178 void givenDeploymentDefaults_whenResolve_thenUseDefaultsAndSuppliedValues () {
163179 resolver =
164- EnvVarResolver .withDeploymentDefaults (
165- Map .of (
166- "DEPLOYMENT_ID" , "deployment-1" ,
167- "USER" , "John" ));
180+ EnvVarResolver .builder ()
181+ .envVars (
182+ withDeploymentDefaults (
183+ Map .of (
184+ "DEPLOYMENT_ID" , "deployment-1" ,
185+ "USER" , "John" )))
186+ .build ();
168187
169188 var result = resolver .resolve ("${DEPLOYMENT_ID}|${DEPLOYMENT_TIMESTAMP}|${USER}" );
170189 var parts = result .split ("\\ |" );
@@ -178,7 +197,10 @@ void givenDeploymentDefaults_whenResolve_thenUseDefaultsAndSuppliedValues() {
178197 @ Test
179198 void givenNonStrictDeploymentDefaults_whenMissingNonDefaultEnvVariable_thenLeavesPlaceholder () {
180199 resolver =
181- EnvVarResolver .withDeploymentDefaults (Map .of ("DEPLOYMENT_ID" , "deployment-1" ), false );
200+ EnvVarResolver .builder ()
201+ .envVars (withDeploymentDefaults (Map .of ("DEPLOYMENT_ID" , "deployment-1" )))
202+ .strict (false )
203+ .build ();
182204
183205 var result = resolver .resolve ("${DEPLOYMENT_ID}|${MISSING}" );
184206
@@ -187,7 +209,7 @@ void givenNonStrictDeploymentDefaults_whenMissingNonDefaultEnvVariable_thenLeave
187209
188210 @ Test
189211 void givenJsonSource_whenResolveInJson_thenResolveStringLeafNodes () throws IOException {
190- resolver = EnvVarResolver .of ( Map .of ("USER" , "John" ));
212+ resolver = EnvVarResolver .builder (). envVars ( Map .of ("USER" , "John" )). build ( );
191213
192214 var result =
193215 resolver .resolveInJson (
@@ -198,4 +220,36 @@ void givenJsonSource_whenResolveInJson_thenResolveStringLeafNodes() throws IOExc
198220 assertThat (json .get ("count" ).asInt ()).isEqualTo (1 );
199221 assertThat (json .get ("nested" ).get ("path" ).asText ()).isEqualTo ("/tmp" );
200222 }
223+
224+ @ Test
225+ void givenSubclass_whenBuild_thenInheritedBuilderFieldsAreApplied () {
226+ resolver =
227+ TestEnvVarResolver .builder ()
228+ .envVars (Map .of ("USER" , "John" ))
229+ .strict (false )
230+ .prefix ("resolved=" )
231+ .build ();
232+
233+ var result = resolver .resolve ("${USER}:${MISSING}" );
234+
235+ assertThat (result ).isEqualTo ("resolved=John:${MISSING}" );
236+ }
237+
238+ private Map <String , String > withDeploymentDefaults (Map <String , String > envVars ) {
239+ var modifiedEnvVars = new HashMap <>(envVars );
240+ EnvUtils .getDeploymentDefaults ().forEach (modifiedEnvVars ::putIfAbsent );
241+
242+ return Map .copyOf (modifiedEnvVars );
243+ }
244+
245+ @ SuperBuilder
246+ private static class TestEnvVarResolver extends EnvVarResolver {
247+
248+ private final String prefix ;
249+
250+ @ Override
251+ public String resolve (String src ) {
252+ return prefix + super .resolve (src );
253+ }
254+ }
201255}
0 commit comments