Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I test code that requires an Environment Variable?

I have some code that requires an Environment Variable to run correctly. But when I run my unit tests, it bombs out once it reaches that point unless I specifically export the variable in the terminal. I am using Scala and sbt. My code does something like this:

class something() {

  val envVar = sys.env("ENVIRONMENT_VARIABLE")

  println(envVar)

}

How can I mock this in my unit tests so that whenever sys.env("ENVIRONMENT_VARIABLE") is called, it returns a string or something like that?

like image 720
Ryan Wilson Avatar asked Dec 01 '15 19:12

Ryan Wilson


People also ask

How do I test environment variables?

On WindowsIn the command window that opens, enter echo %VARIABLE%. Replace VARIABLE with the name of the environment variable you set earlier. For example, to check if MARI_CACHE is set, enter echo %MARI_CACHE%. If the variable is set, its value is displayed in the command window.


2 Answers

If you can't wrap existing code, you can change UnmodifiableMap System.getenv() for tests.

def setEnv(key: String, value: String) = {
  val field = System.getenv().getClass.getDeclaredField("m")
  field.setAccessible(true)
  val map = field.get(System.getenv()).asInstanceOf[java.util.Map[java.lang.String, java.lang.String]]
  map.put(key, value)
}

setEnv("ENVIRONMENT_VARIABLE", "TEST_VALUE1")

If you need to test console output, you may use separate PrintStream. You can also implement your own PrintStream.

val baos = new java.io.ByteArrayOutputStream
val ps = new java.io.PrintStream(baos)
Console.withOut(ps)(
  // your test code
  println(sys.env("ENVIRONMENT_VARIABLE"))
)

// Get output and verify
val output: String = baos.toString(StandardCharsets.UTF_8.toString)
println("Test Output: [%s]".format(output))
assert(output.contains("TEST_VALUE1"))
like image 159
Yuriy Tumakha Avatar answered Oct 09 '22 20:10

Yuriy Tumakha


Ideally, environment access should be rewritten to retrieve the data in a safe manner. Either with a default value ...

scala> scala.util.Properties.envOrElse("SESSION", "unknown")
res70: String = Lubuntu

scala> scala.util.Properties.envOrElse("SECTION", "unknown")
res71: String = unknown

... or as an option ...

scala> scala.util.Properties.envOrNone("SESSION")
res72: Option[String] = Some(Lubuntu)

scala> scala.util.Properties.envOrNone("SECTION")
res73: Option[String] = None

... or both [see envOrSome()].

I don't know of any way to make it look like any/all random env vars are set without actually setting them before running your tests.

like image 30
jwvh Avatar answered Oct 09 '22 19:10

jwvh