Skip to content

Latest commit

 

History

History
84 lines (59 loc) · 3.14 KB

meck.asciidoc

File metadata and controls

84 lines (59 loc) · 3.14 KB

Mocking With Meck

If your code is anything like mine you will find that many of your functions depend heavily on external functions, which may come from the Erlang Standard Library or from other modules that may have been written in house or pulled from the web.

In an ideal world a test should be able to isolate your code from the modules it calls so that you can test your code without having to worry about questions like, the status of an external API or the complex behaviour of a library method.

Therefore for any external functions which are not pure in the functional sense we want to replace them with a simple known function that we know will always do what we want so that only the code under test is

Note
Pure in the functional sense, which is to say that the return value of the function is only a result of the input parameters. You can assume that proplist:get_value/2 will only return values based on the input, while say something in the httpc module will probably require network access, which could cause tests to fail due to things outside your control.

To do that we use a mocking library such as meck which can take functions in other modules and replace them with test functions that allow a simplified truth table.

Meck provides mocks on the level of the Erlang module, before running a test you must setup mocking for that library, then remove it when done.

For example if you want to mock the webmachine wrq:req_body/1 function you might use code like this in this example.

Here we setup the test with meck:new(wrq) which tells meck to mock that module, then in the body of the test we use meck:expect/3 to tell it when the wrq:req_body/1 function is called to call our test function which returns a set binary to the caller. After this we can call wrq:req_body/1 and know exactly what it will return.

setting up meck.erl
link:meck/src/meck_simple.erl[role=include]

Including Meck in your project

The most basic way to include meck in your project is to include it via Rebar, add this to the project’s rebar.config file and run "rebar get_deps" to install it.

rebar.config
{deps, [
       {meck,
        ".*", {git, "git://github.com/eproxus/meck.git", "HEAD"}}]}.

More complex Meck Examples

Places Meck can go wrong

The real problem with mocking frameworks like meck is that they violate the idea of DRY. For example if you have two modules, a and b and you change the way a function works in b you must also change the mocks in a_test.

In addition in the case of meck the order in which rebar compiles your project can matter. If your project consists of many OTP applications in one git repository then if meck can not find a module it will fail. So while in normal compilation order of modules does not matter with meck it does.

Meck version Hell

Sometimes you will include several sub projects with different functionality, the problem is that each of these will often include meck as well. The problem is that often they will include different versions of meck. The problem with this is that rebar will often not compile when the versions don’t match.