[erlang-questions] testing side effects of asynchronous code

Klas Johansson klas.johansson@REDACTED
Fri Jan 6 20:02:19 CET 2012

2012/1/2 Motiejus Jakštys <desired.mta@REDACTED>:
> Hi List,
> Let's say I am testing side effects of this asynchronous function:
> gateway_api:send(Message) -> reference()
> It does some asynchronous processing and produces side effects. After
> processing completes, gen_gwserver:ack_sent is invoked, like this:
> gen_gwserver:ack_sent(Ref :: reference()) -> ok.
> The question is: how can I know that the function ack_sent has been
> called? Then I know that asynchronous work has been completed, so I can
> start validating the side effects.
> An imaginary API in a test case, which blocks until
> gen_gwserver:ack_sent/1 has been called:
> ?call_and_sleep(
>    gateway_api:send(Message),
>    gen_gwserver, ack_sent, 1
> )
> Some options that we ruled out:
> * timer:sleep(some random value)
> * making internal gateway_api:ack(Reference) calls (inconvenient, since
>  necessary only for testing)
> * meck:passthrough looked promising, but the problem is it doesn't
>  return, so it cannot be implemented using meck cleanly.
> Thanks,
> Motiejus Jakštys
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions


I'm biased here, but it sounds like mockgyver [1] could help you out.

mockgyver is a mocking library which also lets you verify
side-effects.  There are a number of ways to verify side-effects, but
the one it sounds you're after is the ?WAIT_CALLED macro and you don't
have to (you can, but you don't have to) mock gen_gwserver in order to
use it.  ?WAIT_CALLED relies on erlang traces for non-mocked modules.
Here's how you'd use it from eunit:


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

setup() ->
    ... start server here, if any ...

cleanup(Pid) ->
    ... stop server here, if any ...

calls_gw_server_ack_test(Pid) ->
    Ref = gateway_api:send(Message),
    ?WAIT_CALLED(gen_gwserver:ack_sent(Ref)), % matches only calls
with ref from above
    ... verify side-effects here, perhaps using ?WAS_CALLED ...


[1] https://github.com/klajo/mockgyver

More information about the erlang-questions mailing list