# ExStub
[![Build Status](](
[![API Docs](](
[![Coverage Status](](
[![Inline docs](](

`ExStub` provides an easy way to stub a module and record the function calls on it.

## Installation

Add `ex_stub` to your deps in `mix.exs` as a development dependency.

def deps do
  [{:ex_stub, "~> 0.1.0", only: :test}]

## Usage

If you have a module in your original application like:

defmodule OriginalModule do
  def process(param), do: :original_process
  def another_method, do: :original_method

You can quickly create a stub copy of this module using `defstub`

use ExStub

defstub MyStub, for: OriginalModule do
  def process(true), do: :stubbed1
  def process(false), do: :stubbed2
  def process(1), do: :stubbed3

Now you can pass around `MyStub` instead of `OriginalModule`.
When you invoke method from the created `MyStub`, if the method was stubbed it will call the stubbed version.
Else the original version will be called.

MyStub.process(true) # returns :stubbed1
MyStub.process(false) # returns :stubbed2
MyStub.process(1) # returns :stubbed3

MyStub.process(20) # returns :original_process

MyStub.another_method # returns :original_method

Notice that Since we did not stub `another_method`, calling it on `MyStub` returns the original implementation.
Also when calling `MyStub.process(20)` the original implementation is called since it failed pattern matching with our stub version of the method.


As a safety procedure, if you try to stub a method that is not found in the original module. ExStub will throw a compilation error telling you about the unexpected stubbed method.

defstub MyStub, for: OriginalModule do
def new_method(), do: :stubbed1

The following error will be thrown

** (RuntimeError) Cannot provide implementations for methods that are not in the original module
The def `{:new_method, 0}` is not defined in module `OriginalModule`

## Recording method calls
All the functions called on the `defstub` created module will be recorded.

To get all the functions calls on `YourModule` module

To get all the `:the_method` function calls on `YourModule` 
ExStub.Recorder.calls(YourModule, :the_method)

Alternativey, you can use `assert_called` in your unit tests:

The syntax is `assert_called ModuleName.function_name(params)`

# No parameters
assert_called ModuleName.function_name

# nil passed
assert_called ModuleName.function_name(nil)

# multiple parameters
assert_called ModuleName.function_name(1, 2)

Some more examples


# Passes since we called the function with [1]
assert_called MyStub.process(1)

# Fails since the parameters dont match
assert_called MyStub.process(1, 2)

# Fails since we did not call `another_method`
assert_called MyStub.another_method