[erlang-questions] mockgyver -- yet another mocking library
Klas Johansson
klas.johansson@REDACTED
Mon Nov 7 22:06:47 CET 2011
Hi Jon,
On Mon, Nov 7, 2011 at 4:19 AM, Jon Watte <jwatte@REDACTED> 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!
Do you have some example code (not for erlymock itself, but rather for
the kind of tests you're referring to here)? The reason I'm asking is
that I'd like to know more.
Myself, I've usually written a bunch of mockgyver's ?WHEN macros in
the setup function (which is run for all tests in a module, see
eunit's fixtures) which I then override using another ?WHEN macro
inside the test functions if they need a different return value.
Then I usually have to write no more than a couple of ?WAS_CALLED (or
one of its cousins) macros to verify that everything I expected
actually happened.
(?WHEN specify the behaviour of a mock in mockgyver, and ?WAS_CALLED
checks that it was called correctly)
> 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 <klas.johansson@REDACTED>
> wrote:
>>
>> Hi Adam,
>>
>> On Fri, Nov 4, 2011 at 4:54 PM, Adam Lindberg
>> <adam.lindberg@REDACTED> 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
>> >> erlang-questions@REDACTED
>> >> http://erlang.org/mailman/listinfo/erlang-questions
>> >
>> >
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>
>
Cheers,
Klas
More information about the erlang-questions
mailing list