Modifier les variables d'environnements en Scala

C'est parfois nécessaire pour des tests unitaires. Le problème est que sys.env, System et ProcessEnvironment sont immuables. Ce n'est pas grave, on va faire un peu de réflexion 😁

def setEnv(name: String, value: String): Unit = {
  val processEnvClass =
    Class.forName("java.lang.ProcessEnvironment")
  val unmodifiableEnvironmentField =
    processEnvClass.getDeclaredField("theUnmodifiableEnvironment")
  unmodifiableEnvironmentField.setAccessible(true)
  val unmodifiableEnvironment =
    unmodifiableEnvironmentField.get(null)

  val unmodifiableMapClass =
    Class.forName("java.util.Collections$UnmodifiableMap")
  val mField =
    unmodifiableMapClass.getDeclaredField("m")
  mField.setAccessible(true)
  val map =
    mField
      .get(theUnmodifiableEnvironment)
      .asInstanceOf[java.util.Map[String, String]]

  map.put(name, value)
}

Note : ça concerne principalement Scala, car dans ce langage on utilise principalement sys.env pour accéder aux variables d'environnement.

En Java, si on passe par System.getenv (majorité des cas), il n'y a pas de problème non plus. sys.env utilise d'ailleurs par cette méthode. Par contre, si vous utilisez, ProcessBuilder.environment vous ne verrez pas de modification dans les variables d'environnement, car cette méthode procède différemment pour les récupérer.

Photographie par Dan Meyers sur Unsplash.