If you want application.ex to be your entry point then you’re limiting yourself to “per started application” composition, which goes against your problem of wanting to run async tests. An application does only once in its lifetime receive “inputs”, so again every additional changes would need to rely on side effects.
If you want async test you need to be able to change plumbing just for the codepath of that single test execution, which for phoenix controller tests means “per request” composition. This requires stuff to be handled somewhere in the plug pipeline. You can see this implemented in action in this blogpost: How to Add Concurrent, Transactional End-To-End Tests in a Phoenix-Powered Ember App - DockYard
Also I’m not saying you need to handle everything in your plug pipeline. You can surely mix and match depending on how much flexibility you really need. Your response sounds like you want plumbing to be static to an application, yet flexible to be tested in isolation. Maybe you should just acknowledge the different levels of granularity and build a multi layered system, where per request plumbing is only done for tests, while in prod the plug simply takes a static set of plumbing from e.g. MyApp.Application.plumbing and put’s it in the current conn. Controllers simply use what’s available to then through the data on the conn.
Processes won’t make your problems simpler in any way. If you use processes to store details on plumbing you still didn’t solve the problem of knowing which process (which set of plumbing) to use for a certain request. If you cannot do that you cannot do async tests with controllers. You might want to look at how e.g. the ecto sandbox works, which essentially deals with the same problem: How does it know which transaction to run a certain db interaction in, so it’s the same as the test starting the current code path.
Basically the answer is global state or explicit “ownership”.


















