Fork me on GitHub
#leiningen
<
2020-06-22
>
nachos13:06:08

Is there a way to set the environment variable before lein test runs?

jumar14:06:57

MYENV=1 lein test ?

noisesmith14:06:44

There are plugins that set environment variables, I don't know which is best though. Environment variables are sadly not first class at all in the jvm without third party extensions with limited cross platform support.

nachos14:06:16

@noisesmith Could you recommend one or two which would do this? I am looking for something that I can configure like this

:profiles {:test {:env {"MYENV" "test"
                  :dependencies [[ring/ring-mock "0.4.0"]]}}

noisesmith14:06:38

lein-environ should work https://github.com/weavejester/environ#installation - it's not the only option though, I can't tell you which is better

noisesmith14:06:02

note there's a lib and a plugin, for what you want the plugin is mandatory

noisesmith14:06:33

(lein can only set the env vars by launching a second vm, that's what the plugin is for)

mikerod14:06:05

You can be super hacky and set Java env variables at runtime in an impl-dependent way (that happens to work across any version in recent history that I’ve seen):

(defn set-env! [env-name env-val]
  (let [e (System/getenv)
        cl (.getClass e)
        field (doto (.getDeclaredField cl "m")
                (.setAccessible true))
        em (.get field e)]
    (.put em env-name env-val)))

noisesmith15:06:10

I wonder if this works on windows (my understanding was that the jvm lacked setenv because win lacked that API...)

mikerod15:06:00

@noisesmith pretty sure it works. It isn’t about setting the actual OS level. It doesn’t do that. Once these main java.lang classes load the process state from the OS - they don’t read it again - or write to it

mikerod15:06:10

At least not in terms of something like the env variables held in the hashtable

mikerod15:06:37

It looks to me to basically be a process-state-cache of env variables - and it’s always used later. If you are looking for OS-level side effects to the process state though - this above won’t work

mikerod15:06:47

but things running within the same VM instance will use your changes

mikerod15:06:57

again though, it’s quite a hack

mikerod15:06:19

it made a few of our testing tools a bit more convenient to write a few things for - and we know it’s not a real API and we could have to change at some point

noisesmith15:06:36

right - this was answered by your later point about the field being mutated not effecting the actual process env, just an internal representation

noisesmith15:06:54

I had asked that before I figured that out

mikerod15:06:51

Oh, sorry. Misread I guess.

noisesmith15:06:08

it's OK - it's thread vs. main channel timing :D

mikerod15:06:24

concurrency troubles

nachos15:06:28

@mikerod Is it possible to set this before lein test starts?

jumar15:06:03

How do you use those env vars? Can system properties be used instead? (I do this with our config tests)

noisesmith15:06:47

lein-env, linked above, supports this. And something multiple libraries offer is a merge of config from a file, the environment, and jvm system properties, so that you can set things via env in prod, and use files and programmatic property setting for local dev.

noisesmith15:06:07

env and aero each support some variant of that

mikerod16:06:42

@danisam17 yeah, it could be done as a :prep-tasks or something probably. I’m not sure this is the best approach to do things - I’ve used it but only in a testing tool with important caveats that I verified it worked on like JDK8 through 11 so far on an OpenJDK based JVM

mikerod16:06:58

the funny part of Java’s env variables is just that they are loaded and stored in a mutable hashtable

mikerod16:06:08

and after that - that’s the Java “source of truth”

mikerod16:06:32

so you can mutate it… (of course this does require open security priv’s, which you’d have in cases where you’re running the system etc)

noisesmith16:06:23

oh so that technique isn't actually changing the process environment, just the mutable table that's used to look it up?