MockBehaviour v0.1.4 MockBehaviour View Source

MockBehaviour helps you maintain mocks for your behaviours.

This code is inspired by the pattern shown in Jose Valim’s article on mocks ( http://blog.plataformatec.com.br/2015/10/mocks-and-explicit-contracts/ ).

Assume the following behaviour:

defmodule TwitterContract do
  @callback tweets(user_id :: String.t) :: [map()]
end

defmodule TwitterContractHttp do
  @behaviour TwitterContract
  def tweets(user_id), do: # call to Twitter, return desired tweets
end

At this point, your code might be using TwitterContractHttp and you are now inextricably bound to an external service.

Not so! You can create an API to get to your external services, and use mocks at that level. All you have to do is this:

defmodule Contracts do
  @behaviour TwitterContract
  @twitter Application.get_env(:app, :contracts)[:twitter_module]

  def tweets(user_id), do: @twitter.tweets(user_id)
end

And you can configure your system like so:

# dev
config :app, :contracts, [
  twitter_module: TwitterContractHttp
]

# test
config :app, :contracts, [
  twitter_module: TwitterContractMock
]

At this point, to reap the rewards from this package, all you have to do is:

defmodule TwitterContractMock do
  use MockBehaviour, behaviour: TwitterContract
end

This will generate the following code:

defmodule TwitterContractMock do
  use GenServer
  def start_link(state) do
    GenServer.start_link(__MODULE__, state, name: __MODULE__)
  end

  def tweets(user_id) do
    GenServer.call(__MODULE__, {:tweets, user_id})
  end

  def handle_call({:tweets, user_id}, _from, state) do
    response = state.tweets.(user_id)
    {:reply, response, state}
  end
end

From there, in your tests you can simply define and use an anonymous function:

tweets = fn(x) -> [%{tweet: "This package is such a timesaver", user: "Trevoke" }]

TwitterContractMock.start_link(%{tweets: tweets})

Enjoy your self-maintaining mocks!

Link to this section Summary

Link to this section Functions

Link to this macro handle_mock_call(x, y) View Source (macro)