Skip to content

Commit

Permalink
Added mocking helpers for working with eunit tests
Browse files Browse the repository at this point in the history
Features include:

* Imports mocking helper functions and gives access to helper macros.

* Clear division of intent between creating a stub
version of existing module/function and creating a fake
module/function that should not exist already on the code
path.

* Lazy mocking of modules to reduce duplication between
meck:new and meck:expect lines.

* EUnit fixture helper which runs all functions in the module
as EUnit tests w/o need for specific pre/suffix, wrapping each
one with a meck:unload after (even if test results in error).
The fixture also allows for setup/teardown function names to be
passed in which will be run before/after each test regardless
of test outcome.

Authors:
Benjamin Lee, Matt Campbell, Mike Lazar, Kenny Ortmann, Nate McKie, and Oliver Ferrigni
  • Loading branch information
codev2 committed Dec 29, 2011
1 parent b0eea7e commit e114b45
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 0 deletions.
55 changes: 55 additions & 0 deletions src/mocking.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
-module(mocking).
-compile([export_all]).

stub(M, F, A, R) ->
stub(M),
meck:expect(M, F, A, R).

stub_sequence(M, F, A, Rs) ->
stub(M),
meck:sequence(M, F, A, Rs).

fake(M, F, A, R) ->
fake(M),
meck:expect(M, F, A, R).

should_never_call(Module) ->
meck:new(Module, [no_link]).

% ---- INTERNALS ----

stub(M) ->
mock(M, stub_options).

fake(M) ->
mock(M, fake_options).

mock(M, MeckOptionsFun) ->
case module_already_mocked(M) of
false -> meck:new(M, ?MODULE:MeckOptionsFun(M));
true -> noop
end.

module_already_mocked(Module) ->
case erlang:whereis(meck_process_name(Module)) of
undefined -> false;
_ -> true
end.

meck_process_name(Module) ->
list_to_atom(atom_to_list(Module) ++ "_meck").

stub_options(M) ->
{module, M} = code:ensure_loaded(M),

case code:is_sticky(M) of
true ->
[no_link, unstick];
false ->
[no_link]
end.

fake_options(M) ->
false = code:is_loaded(M),

[no_link].
23 changes: 23 additions & 0 deletions src/mocking.hrl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-import(mocking, [stub/4, stub_sequence/4, fake/4, should_never_call/1]).

-define(MOCK_FIXTURE_NAME, mock_fixture_test_).

% add eunit test fixture to module which runs all other functions as tests
% wrapped with meck unload
-define(MOCK_FIXTURE(Setup, Teardown),
?MOCK_FIXTURE_NAME() ->
{foreach,
fun() -> Setup() end,
fun(X) -> Teardown(X), meck:unload() end,
[
{?MODULE, F} || {F, _A} <- ?MODULE:module_info(exports),
F =/= ?MOCK_FIXTURE_NAME
andalso F =/= test
andalso F =/= module_info
andalso F =/= Setup
andalso F =/= Teardown
]
}
).

-define(MOCK_FIXTURE, ?MOCK_FIXTURE(fun() -> noop end, fun(_) -> noop end)).

0 comments on commit e114b45

Please sign in to comment.