Is there a way to set the environment variable before lein test
runs?
MYENV=1 lein test ?
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.
@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"]]}}
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
note there's a lib and a plugin, for what you want the plugin is mandatory
(lein can only set the env vars by launching a second vm, that's what the plugin is for)
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)))
@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
At least not in terms of something like the env variables held in the hashtable
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
but things running within the same VM instance will use your changes
again though, it’s quite a hack
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
right - this was answered by your later point about the field being mutated not effecting the actual process env, just an internal representation
I had asked that before I figured that out
Oh, sorry. Misread I guess.
it's OK - it's thread vs. main channel timing :D
concurrency troubles
oh, wow...
@mikerod Is it possible to set this before lein test
starts?
I wonder if this works on windows (my understanding was that the jvm lacked setenv because win lacked that API...)
How do you use those env vars? Can system properties be used instead? (I do this with our config tests)
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.
env and aero each support some variant of that
@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
the funny part of Java’s env variables is just that they are loaded and stored in a mutable hashtable
and after that - that’s the Java “source of truth”
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)
oh so that technique isn't actually changing the process environment, just the mutable table that's used to look it up?
yep