[erlang-questions] mockgyver -- yet another mocking library

Klas Johansson <>
Mon Nov 7 21:56:27 CET 2011


Hi,

On Mon, Nov 7, 2011 at 4:48 PM, Tim Watson <> wrote:
> If you want to mock OTP behaviours, then I'd suggest looking
> at https://github.com/noss/emock, which is really good for that.

For gen_server and the like, I always write a client API, i.e. write
functions within the module that implements the gen_server that call
gen_server:call/3 etc:

    inc_counter(Pid, Name) -> gen_server:call(Pid, {inc_counter,
Name}, ?TIMEOUT).

That way I can easily mock inc_counter/2 if I have to (or change the
implementation from a gen_server to something else for that matter).


Cheers,
Klas

> On 7 November 2011 03:19, Jon Watte <> wrote:
>>
>> When it comes to mocking, I know that this is one option, and a number of
>> people are recommending meck. However, both of these use the "sort it all
>> out afterwards" approach, which I personally feel is not strict enough. When
>> you mock, you want to mock for a few reasons:
>> 1) You want plausible data to be returned from unrelated modules. You
>> don't really need to go to a disk mnesia table to test your configuration
>> parser :-)
>> 2) You want to enforce that, when functions are called, parameters conform
>> to certain parameters. This may be "is exactly x,z,y" or just "is numeric"
>> or whatever.
>> 3) You want to enforce the presence or absence of specific calls with
>> specific parameters.
>> I find that the "setup" then "replay" mechanism of erlymock (by Jason
>> Wagner) is almost ideally suited to these cases -- and, once I mocked, and
>> run my code, the system automatically verifies my expectations; I don't have
>> to go trawling through any captured results of calls to try to verify
>> whether they are good or not!
>> Now, in cases where you want to mock gen_server, or erlang, the code
>> replacement approach used just won't work. I don't think there's much of a
>> way around that, other than to use shallow wrappers in your own code, and
>> mock those wrappers.
>> Personally, I really wish that module got some more public love in the
>> Erlang community. To me, it does it close to Right(tm).
>> Sincerely,
>> jw
>>
>> --
>> Americans might object: there is no way we would sacrifice our living
>> standards for the benefit of people in the rest of the world. Nevertheless,
>> whether we get there willingly or not, we shall soon have lower consumption
>> rates, because our present rates are unsustainable.
>>
>>
>>
>> On Sun, Nov 6, 2011 at 3:19 AM, Klas Johansson <>
>> wrote:
>>>
>>> Hi Adam,
>>>
>>> On Fri, Nov 4, 2011 at 4:54 PM, Adam Lindberg
>>> <> wrote:
>>>
>>> > Nice to see more mocking tools popping up!
>>>
>>> :-)
>>>
>>> >  - Is it tied to EUnit or generic?
>>>
>>> It's generic (the ?MOCK macro is generic, although the
>>> ?WITH_MOCKED_SETUP macro is intended for use from eunit).
>>>
>>> >  - What happens when a function is called with other parameters than
>>> > those expected?
>>>
>>> Nothing.  If I write a "guard" like this:
>>>
>>>    ?WAS_CALLED(lists:nth(2, [a, b, c])),
>>>
>>> that call will succeed if the function was called with those
>>> parameters once.  If it was called with those parameters for example
>>> twice (or never) it'll fail (like an assert macro in eunit).  If it
>>> was called once with those parameters, and once with another set of
>>> parameters it still succeeds.
>>>
>>> If you want to check that the function was only called once with those
>>> parameters and no other parameters you can do something like this:
>>>
>>>   [[2, [a, b, c]]] = ?WAS_CALLED(lists:nth(_, _)),
>>>
>>> since ?WAS_CALLED (as well as ?WAIT_CALLED and ?GET_CALLS) will always
>>> return a list of argument lists.
>>>
>>> Not as concise.  Perhaps a better syntax for those cases will make it
>>> into a future version. :-)
>>>
>>> >  - How's the beam renaming working out for you so far? Have you seen
>>> > any cases in
>>> >   where it hasn't been able to find all occurrences of a module name?
>>>
>>> So far it's done its job, but it's not really bullet proof.  Haven't
>>> had the need to call the original module frequently enough to bump
>>> into problems.  The algorithm only replaces the atom within the atom
>>> table, but not within the constant pool.  mockgyver works for modules
>>> both with and without debug_info, but I've been thinking of changing
>>> that:
>>>
>>> * use debug_info when available
>>> * otherwise, resort to replacing within the beam code
>>>
>>> It's not been an issue so far, but if people start using this and bump
>>> into problems I'll prioritize it.
>>>
>>> >  - really nice syntax (thanks to parse transforms).
>>>
>>> Thanks!
>>>
>>> > Is there a functional API?
>>>
>>> Yes and no.  There is, but it's not documented and may change.
>>> However, nothing is set in stone. If there are good reasons for adding
>>> such an interface it'll be done.
>>>
>>> Cheers,
>>> Klas
>>>
>>> > On 2011-11-02, at 21:47 , Klas Johansson wrote:
>>> >
>>> >> Hi all,
>>> >>
>>> >> I'd like you to meet mockgyver -- an Erlang tool which will make it
>>> >> easier to write EUnit tests that 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.  Let's redefine pi to 4:
>>> >>
>>> >>       ?WHEN(math:pi() -> 4),
>>> >>       4 = math:pi(),
>>> >>
>>> >> Use pattern matching to check that a function was called with certain
>>> >> arguments:
>>> >>
>>> >>       ?WAS_CALLED(lists:reverse([a, b, c])),
>>> >>
>>> >> ... or if you don't care about the arguments:
>>> >>
>>> >>       ?WAS_CALLED(lists:reverse(_)),
>>> >>
>>> >> The library has been in use for a year for a bunch of Erlang
>>> >> applications, except for a couple of recent additions.
>>> >>
>>> >> A short tutorial as well as docs and many more examples[1] in markdown
>>> >> format on github:
>>> >>
>>> >>    https://github.com/klajo/mockgyver
>>> >>
>>> >>
>>> >> Cheers,
>>> >> Klas
>>> >>
>>> >> [1] https://github.com/klajo/mockgyver/blob/master/doc/mockgyver.md
>>> >> _______________________________________________
>>> >> erlang-questions mailing list
>>> >> 
>>> >> http://erlang.org/mailman/listinfo/erlang-questions
>>> >
>>> >
>>> _______________________________________________
>>> erlang-questions mailing list
>>> 
>>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> 
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>
>



More information about the erlang-questions mailing list