When I run mix test, the supervision tree declared in Application.ex attempts to start, which in turn attempts to start AMQP connections, but because the AMQP broker is unavailable in the test environment, it causes the boot sequence to fail. I’d like to mock or stub AMQP and S3 so the application can be exercised in isolation.
What is the most reliable pattern (libraries, configuration, or architectural changes) for achieving this, while still ensuring the behaviour of the real services is adequately represented? Which combination of libraries, configuration tweaks, or architectural adjustments will let me do this while still giving a faithful representation of the real services’ behaviour?
1 Answer
What is the most reliable pattern (libraries, configuration, or architectural changes) for achieving this
There's not much in it that's unique to Elixir. In general, you should abstract away any dependency on the infrastructure if you cannot provide the equivalent of it during testing.
For architectural patterns, I usually go with Ports and Adapters but any would do fine here.
The hexagonal architecture, or ports and adapters architecture, is an architectural pattern used in software design. It aims at creating loosely coupled application components that can be easily connected to their software environment by means of ports and adapters. This makes components exchangeable at any level and facilitates test automation.
You can represent ports using Elixir's behaviour modules.
Behaviours in Elixir (and Erlang) are a way to separate and abstract the generic part of a component (which becomes the behaviour module) from the specific part (which becomes the callback module).
In this case, AMQP implementation becomes an adapter and you substitute it out with another implementation during the test run.
while still ensuring the behaviour of the real services is adequately represented?
There's no substitute for the real thing. You can replicate the behaviour of the real service to some extend but this might not be enough especially if the underlying service changes its contract or if there are cases that you haven't accounted for.