Mocking in Elixir

Yuri Brito
SkyHub Labs
Published in
2 min readJul 17, 2017

Sometimes, for whatever reason, we need some module’s function to behave differently when running in different environments.

For example, we don’t always need tests making real requests to external services in order to be sure that functions that consume or produce data are working as intended.

With that in mind, it’s possible to create modules in elixir that have the same interface yet are used only when in their respective desired environment.

In this example application, we’re going to request a json and print it’s data in a specific format: “id: FirstName LastName”.

In a real application, it would probably be better to modularize and separate concerns a bit more.

Now let’s write a test and make the assumption that requesting “testing.com/json/1” would have the following JSON response:

By using a service like http://www.mocky.io/, you can replace Requester.get(“…”) with the generated url and make the test pass.

Now, if all you have to test is the way App.concat/1 is going to format the input data and output it’s value, you don’t need your tests making external HTTP requests every time they run.

Let’s mock the Requester module and make Requester.get/1 output different data depending on how it’ll pattern match the parameters.

One way to use different modules depending on the environment is to create configurations. After “import_config “#{Mix.env}.exs”” to config/config.exs, mix will load the respective config file for your environment (eg. config/test.exs).

Then, we need to make our App module use the requester module defined by this config, instead of hard coding which one is used.

I usually place mocks either in lib/mocks/ or test/mocks. If they are placed in test/mocks, we have to load them inside test/test_helper.exs

Code.load_file(“test/mocks/requester.ex”)

Finally, the mock:

We can even mock only some of the requests (ids, in this case), and in others use the real service.

--

--