I have a question for people who have been using bypass for testing web requests. How do you handle asynchronous tests where the code making the request is pretty far into your Phoenix context?
If I’m testing the module that makes the request directly then as an optional argument I can pass the url with the bypass port, but if the request is happening further down the call stack then I don’t want to be passing that url all the way through the application.
Do people just use mox/meck for this instead?
2 Likes
whenever I’m in a situation similar to the one you’re describing, I typically make the module that calls the external service configurable so that the external service’s url can be passed as a config parameter. Then, in the config for the test environment (test.exs
), I set the url to be the bypass
url.
Yes, I’ve done that too, but the problem then is because we’re setting the application env to a test-specific value, we can no longer use async: true
because the application environment is global configuration.
Not sure I understand. async: true
affects concurrency of test cases right? How does it affect configuration?
Sorry if this is unhelpful, but the challenges you’re facing is the reason I’m using Mox which you can use in async tests. I think to make this work with bypass you’ll end up with pretty much similar mechanism that you’d use for Mox.
@stefanchrobot can you explain to me what the challenge is? I’m curious 
Why can’t you use bypass
in async tests? Is it because each test will spawn its own bypass process and there will be a conflict if they are all trying to bind to the same TCP port?
If I’m not mistaken, you can’t do Application.put_env
(and revert it at the end) in async tests because the tests will override the values. As you mentioned, you can do it globally in config/test.exs
, but the way I understood it is that @axelson doesn’t want a global config.
So it seems the options are:
-
async: false
with Application.put_env
,
-
async: true
with global config,
-
async: true
with Mox (it uses a global config to replace the real module with the mock).
3 Likes
Oh I see now. Thanks! Yes that sounds right. The question of course is "do you really need to set up your test using Application.put_env
"? Personally, it’s something that I try to avoid like the plague 
You can look at how we tackled this in Bytepack: bytepack_archive/stripe_helpers.ex at main · dashbitco/bytepack_archive · GitHub
We defined a behaviour for the host (in this case Stripe) and then used Mox to set the Bypass URL as the host.
4 Likes
The way we handle this is by having our own config module which is just a wrapper around Application.get_env. If the env is not test, it will just call Application.get_env. If test, it will first check if there are any overrides for the given key and current process. It will also take $callers and $ancestors into account while doing the lookup. We do use Mox in many other cases, but for http api we mostly depend on bypass with the config override
Thanks! I’ll study that in more detail tomorrow.