Giter VIP home page Giter VIP logo

mockgyver's Introduction

mockgyver

Hex pm Build Status Erlang Versions

mockgyver is an Erlang tool which will make it easier to write EUnit tests which need to replace or alter (stub/mock) the behaviour of other modules.

mockgyver aims to make that process as easy as possible with a readable and concise syntax.

mockgyver is built around two main constructs: ?WHEN which makes it possible to alter the behaviour of a function and another set of macros (like ?WAS_CALLED) which check that a function was called with a chosen set of arguments.

Read more about constructs and syntax in the documentation for the mockgyver module.

The documentation is generated using the edown extension which generates documentation which is immediately readable on github. Remove the edown lines from rebar.config to generate regular edoc.

A quick tutorial

Let's assume we want to make sure a fictional program sets up an ssh connection correctly (in order to test the part of our program which calls ssh:connect/3) without having to start an ssh server. Then we can use the ?WHEN macro to replace the original ssh module and let connect/3 return a bogus ssh_connection_ref():

    ?WHEN(ssh:connect(_Host, _Port, _Opts) -> {ok, ssh_ref}),

Also, let's mock close/1 while we're at it to make sure it won't crash on the bogus ssh_ref:

    ?WHEN(ssh:close(_ConnRef) -> ok),

When testing our program, we want to make sure it calls the ssh module with the correct arguments so we'll add these lines:

    ?WAS_CALLED(ssh:connect({127,0,0,1}, 2022, [])),
    ?WAS_CALLED(ssh:close(ssh_ref)),

For all of this to work, the test needs to be encapsulated within either the ?MOCK macro or the ?WITH_MOCKED_SETUP (recommended for eunit). Assume the test case above is within a function called sets_up_and_tears_down_ssh_connection:

    sets_up_and_tears_down_ssh_connection_test() ->
        ?MOCK(fun sets_up_and_tears_down_ssh_connection/0).

Or, if you prefer ?WITH_MOCKED_SETUP:

    ssh_test_() ->
        ?WITH_MOCKED_SETUP(fun setup/0, fun cleanup/1).

    sets_up_and_tears_down_ssh_connection_test(_) ->
        ...

Sometimes a test requires a process to be started before a test, and stopped after a test. In that case, the latter is better (it'll automatically export and call all ...test/1 functions).

The final test case could look something like this:

    -include_lib("mockgyver/include/mockgyver.hrl").

    ssh_test_() ->
        ?WITH_MOCKED_SETUP(fun setup/0, fun cleanup/1).

    setup() ->
        ok.

    cleanup(_) ->
        ok.

    sets_up_and_tears_down_ssh_connection_test(_) ->
        ?WHEN(ssh:connect(_Host, _Port, _Opts) -> {ok, ssh_ref}),
        ?WHEN(ssh:close(_ConnRef) -> ok),
        ...start the program and trigger the ssh connection to open...
        ?WAS_CALLED(ssh:connect({127,0,0,1}, 2022, [])),
        ...trigger the ssh connection to close...
        ?WAS_CALLED(ssh:close(ssh_ref)),

API documentation

See mockgyver for details.

Caveats

There are some pitfalls in using mockgyver that you might want to know about.

  • It's not possible to mock local functions.

    This has to do with the way mockgyver works through unloading and loading of modules.

  • Take care when mocking modules which are used by other parts of the system.

    Examples include those in stdlib and kernel. A common pitfall is mocking io. Since mockgyver is potentially unloading and reloading the original module many times during a test suite, processes which are running that module may get killed as part of the code loading mechanism within Erlang. A common situation when mocking io is that eunit will stop printing the progress and you will wonder what has happened.

  • NIFs cannot be mocked and mockgyver will try to inform you if that is the case.

  • mockgyver does currently not play well with cover and cover will complain that a module has not been cover compiled. This is probably solvable.

History

It all started when a friend of mine (Tomas Abrahamsson) and I (Klas Johansson) wrote a tool we called the stubber. Using it looked something like this:

    stubber:run_with_replaced_modules(
        [{math, pi, fun() -> 4 end},
         {some_module, some_function, fun(X, Y) -> ... end},
         ...],
        fun() ->
            code which should be run with replacements above
        end),

Time went by and we had test cases which needed a more intricate behaviour, the stubs grew more and more complicated and that's when I thought: it must be possible to come up with something better and that's when I wrote mockgyver.

Using mockgyver with your own application

mockgyver is available as a hex package. Just add it as a dependency to your rebar.config:

{deps, [mockgyver]}.

... or with a specific version:

{deps, [{mockgyver, "some.good.version"}]}.

Building

Build mockgyver using rebar. Also, parse_trans (for the special syntax), edown (for docs on github) and eunit_addons (for ?WITH_MOCKED_SETUP) are required, but rebar takes care of that.

$ git clone git://github.com/klajo/mockgyver.git
$ rebar3 compile

Build docs using the edown library (for markdown format):

$ rebar3 as edown edoc

Build regular docs:

$ rebar3 edoc

mockgyver's People

Contributors

klajo avatar tomas-abrahamsson avatar mhssler avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.