@@ -4,6 +4,7 @@ package utils_test
44import (
55 "math"
66 "os"
7+ "path/filepath"
78 "strconv"
89 "testing"
910 "time"
@@ -12,6 +13,13 @@ import (
1213 "github.com/stretchr/testify/require"
1314)
1415
16+ // simpleTestEnv creates a test environment that doesn't depend on filesystem operations
17+ // to avoid race conditions with tests that change working directories
18+ func simpleTestEnv () utils.Env {
19+ provider := & utils.OSEnvProvider {}
20+ return utils.Env {EnvProvider : provider }
21+ }
22+
1523func TestGetEnvVariables (t * testing.T ) {
1624 t .Parallel ()
1725 assertRoot := require .New (t )
@@ -60,10 +68,20 @@ func TestGetEnvVariables(t *testing.T) {
6068 for _ , test := range tests {
6169 test := test // capture
6270 t .Run ("Test_" + test .key , func (t * testing.T ) {
63- provider := utils .NewTestEnv (t )
6471 t .Parallel ()
65- provider .Set (test .key , test .value )
66- test .assert (provider , test )
72+ provider := simpleTestEnv ()
73+
74+ // Set environment variable directly
75+ envKey := "TEST_" + test .key
76+ _ = os .Setenv (envKey , test .value )
77+ defer func () {
78+ _ = os .Unsetenv (envKey )
79+ }()
80+
81+ // Update the test to use the new key
82+ testCopy := test
83+ testCopy .key = envKey
84+ testCopy .assert (provider , testCopy )
6785 })
6886 }
6987}
@@ -117,16 +135,26 @@ func TestGetInt_OverflowInt16(t *testing.T) {
117135
118136func TestGetUint_NegativeValue (t * testing.T ) {
119137 t .Parallel ()
120- p := utils .NewTestEnv (t )
121- p .Set ("UINT_NEG" , "-5" )
122- require .Panics (t , func () { _ = utils .GetUintEnv [uint ](p , "UINT_NEG" , 0 ) })
138+ p := simpleTestEnv ()
139+
140+ _ = os .Setenv ("UINT_NEG_TEST" , "-5" )
141+ defer func () {
142+ _ = os .Unsetenv ("UINT_NEG_TEST" )
143+ }()
144+
145+ require .Panics (t , func () { _ = utils .GetUintEnv [uint ](p , "UINT_NEG_TEST" , 0 ) })
123146}
124147
125148func TestGetUint_OverflowUint8 (t * testing.T ) {
126149 t .Parallel ()
127- p := utils .NewTestEnv (t )
128- p .Set ("U8_OVERFLOW" , "256" ) // > 255
129- require .Panics (t , func () { _ = utils .GetUintEnv [uint8 ](p , "U8_OVERFLOW" , 0 ) })
150+ p := simpleTestEnv ()
151+
152+ _ = os .Setenv ("U8_OVERFLOW_TEST" , "256" ) // > 255
153+ defer func () {
154+ _ = os .Unsetenv ("U8_OVERFLOW_TEST" )
155+ }()
156+
157+ require .Panics (t , func () { _ = utils .GetUintEnv [uint8 ](p , "U8_OVERFLOW_TEST" , 0 ) })
130158}
131159
132160func TestGetFloat_InvalidEmpty (t * testing.T ) {
@@ -143,26 +171,50 @@ func TestGetBool_InvalidValues(t *testing.T) {
143171 v := v
144172 t .Run (v , func (t * testing.T ) {
145173 t .Parallel ()
146- p := utils .NewTestEnv (t )
147- p .Set ("BOOL_BAD_GENERIC" , v )
148- require .Panics (t , func () { _ = utils .GetBoolEnv (p , "BOOL_BAD_GENERIC" , false ) })
174+ // Use a simple test environment that doesn't depend on project root
175+ provider := & utils.OSEnvProvider {}
176+ p := utils.Env {EnvProvider : provider }
177+
178+ // Set the invalid value directly in the environment
179+ envKey := "BOOL_BAD_GENERIC_" + v
180+ _ = os .Setenv (envKey , v )
181+ defer func () {
182+ _ = os .Unsetenv (envKey )
183+ }()
184+
185+ require .Panics (t , func () { _ = utils .GetBoolEnv (p , envKey , false ) })
149186 })
150187 }
151188}
152189
153190func TestGetDurationEnv_FallbackLargeSeconds (t * testing.T ) {
154191 t .Parallel ()
155- p := utils .NewTestEnv (t )
156- p .Set ("DUR_LARGE_SECS" , "7200" ) // 2h fallback path
157- got := utils .GetDurationEnv (p , "DUR_LARGE_SECS" , time .Second )
192+ // Use a simple test environment that doesn't depend on project root
193+ provider := & utils.OSEnvProvider {}
194+ p := utils.Env {EnvProvider : provider }
195+
196+ // Set the value directly in the environment
197+ _ = os .Setenv ("DUR_LARGE_SECS_TEST" , "7200" ) // 2h fallback path
198+ defer func () {
199+ _ = os .Unsetenv ("DUR_LARGE_SECS_TEST" )
200+ }()
201+ got := utils .GetDurationEnv (p , "DUR_LARGE_SECS_TEST" , time .Second )
158202 require .Equal (t , 2 * time .Hour , got )
159203}
160204
161205func TestGetDurationEnv_EmptyPanics (t * testing.T ) {
162206 t .Parallel ()
163- p := utils .NewTestEnv (t )
164- p .Set ("DUR_EMPTY" , "" )
165- require .Panics (t , func () { _ = utils .GetDurationEnv (p , "DUR_EMPTY" , time .Minute ) })
207+ // Use a simple test environment that doesn't depend on project root
208+ provider := & utils.OSEnvProvider {}
209+ p := utils.Env {EnvProvider : provider }
210+
211+ // Set the empty value directly in the environment
212+ _ = os .Setenv ("DUR_EMPTY_TEST" , "" )
213+ defer func () {
214+ _ = os .Unsetenv ("DUR_EMPTY_TEST" )
215+ }()
216+
217+ require .Panics (t , func () { _ = utils .GetDurationEnv (p , "DUR_EMPTY_TEST" , time .Minute ) })
166218}
167219
168220func TestGetEnv_EmptyStringVsMissing (t * testing.T ) {
@@ -194,10 +246,16 @@ func TestParallelIsolation(t *testing.T) {
194246 i := i
195247 t .Run ("iso_" + time .Duration (i ).String (), func (t * testing.T ) {
196248 t .Parallel ()
197- p := utils . NewTestEnv ( t )
198- key := "K " + strconv .Itoa (i )
249+ p := simpleTestEnv ( )
250+ key := "ISO_K " + strconv .Itoa (i )
199251 val := strconv .Itoa (100 + i )
200- p .Set (key , val )
252+
253+ // Set environment variable directly
254+ _ = os .Setenv (key , val )
255+ defer func () {
256+ _ = os .Unsetenv (key )
257+ }()
258+
201259 require .Equal (t , 100 + i , utils .GetIntEnv [int ](p , key , 0 ))
202260 })
203261 }
@@ -221,18 +279,28 @@ func TestGetAllIntTypesParsing(t *testing.T) {
221279
222280func TestGetAllIntTypesOverflow (t * testing.T ) {
223281 t .Parallel ()
224- p := utils .NewTestEnv (t )
225- p .Set ("INT8_OVER" , "128" ) // > 127
226- p .Set ("INT16_OVER" , "40000" ) // > 32767
227- p .Set ("INT32_OVER" , "2147483648" ) // > int32 max
228- p .Set ("INT64_OVER" , "9223372036854775808" ) // > int64 max
229- p .Set ("INT_STD_OVER" , "9223372036854775808" )
230-
231- require .Panics (t , func () { _ = utils .GetIntEnv [int8 ](p , "INT8_OVER" , 0 ) })
232- require .Panics (t , func () { _ = utils .GetIntEnv [int16 ](p , "INT16_OVER" , 0 ) })
233- require .Panics (t , func () { _ = utils .GetIntEnv [int32 ](p , "INT32_OVER" , 0 ) })
234- require .Panics (t , func () { _ = utils .GetIntEnv [int64 ](p , "INT64_OVER" , 0 ) })
235- require .Panics (t , func () { _ = utils .GetIntEnv [int ](p , "INT_STD_OVER" , 0 ) })
282+ p := simpleTestEnv ()
283+
284+ // Set environment variables directly
285+ _ = os .Setenv ("INT8_OVER_TEST" , "128" ) // > 127
286+ _ = os .Setenv ("INT16_OVER_TEST" , "40000" ) // > 32767
287+ _ = os .Setenv ("INT32_OVER_TEST" , "2147483648" ) // > int32 max
288+ _ = os .Setenv ("INT64_OVER_TEST" , "9223372036854775808" ) // > int64 max
289+ _ = os .Setenv ("INT_STD_OVER_TEST" , "9223372036854775808" )
290+
291+ defer func () {
292+ _ = os .Unsetenv ("INT8_OVER_TEST" )
293+ _ = os .Unsetenv ("INT16_OVER_TEST" )
294+ _ = os .Unsetenv ("INT32_OVER_TEST" )
295+ _ = os .Unsetenv ("INT64_OVER_TEST" )
296+ _ = os .Unsetenv ("INT_STD_OVER_TEST" )
297+ }()
298+
299+ require .Panics (t , func () { _ = utils .GetIntEnv [int8 ](p , "INT8_OVER_TEST" , 0 ) })
300+ require .Panics (t , func () { _ = utils .GetIntEnv [int16 ](p , "INT16_OVER_TEST" , 0 ) })
301+ require .Panics (t , func () { _ = utils .GetIntEnv [int32 ](p , "INT32_OVER_TEST" , 0 ) })
302+ require .Panics (t , func () { _ = utils .GetIntEnv [int64 ](p , "INT64_OVER_TEST" , 0 ) })
303+ require .Panics (t , func () { _ = utils .GetIntEnv [int ](p , "INT_STD_OVER_TEST" , 0 ) })
236304}
237305
238306func TestGetAllUintTypesParsing (t * testing.T ) {
@@ -414,47 +482,25 @@ func TestNewEnv(t *testing.T) {
414482 require .NotNil (t , env .EnvProvider )
415483}
416484
417- func TestLoadDotEnv_Success (t * testing.T ) {
485+ func TestLoadDotEnv_LoadError (t * testing.T ) {
418486 t .Parallel ()
419487
420- // Create a temporary .env file for testing successful loading
421- envContent := "TEST_VAR=test_value\n "
422- err := os .WriteFile (".env" , []byte (envContent ), 0o644 )
488+ // Create a temporary directory for this test to avoid interfering with other tests
489+ tmpDir , err := os .MkdirTemp ("" , "env-test-*" )
423490 require .NoError (t , err )
424491 defer func () {
425- _ = os .Remove ( ".env" )
492+ _ = os .RemoveAll ( tmpDir )
426493 }()
427494
428- // This should not panic and should load successfully
429- require .NotPanics (t , func () {
430- utils .LoadDotEnv ()
431- })
432-
433- // Verify the variable was loaded
434- value := os .Getenv ("TEST_VAR" )
435- require .Equal (t , "test_value" , value )
436-
437- // Clean up
438- err = os .Unsetenv ("TEST_VAR" )
439- if err != nil {
440- t .Fatalf ("failed to unset env var: %v" , err )
441- }
442- }
443-
444- func TestLoadDotEnv_LoadError (t * testing.T ) {
445- t .Parallel ()
446-
447495 // Create an invalid .env file that will cause godotenv.Load to fail
448496 invalidEnvContent := "INVALID_LINE_WITHOUT_EQUALS\n "
449- err := os .WriteFile (".env" , []byte (invalidEnvContent ), 0o644 )
497+ envFile := filepath .Join (tmpDir , ".env" )
498+ err = os .WriteFile (envFile , []byte (invalidEnvContent ), 0o644 )
450499 require .NoError (t , err )
451- defer func () {
452- _ = os .Remove (".env" )
453- }()
454500
455501 // This should not panic but should log an error and return
456502 require .NotPanics (t , func () {
457- utils .LoadDotEnv ( )
503+ utils .MustLoadEnv ( tmpDir )
458504 })
459505}
460506
0 commit comments