[erlang-questions] testing side effects of asynchronous code
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:
> 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.
> Motiejus Jakštys
> erlang-questions mailing list
I'm biased here, but it sounds like mockgyver  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:
?WITH_MOCKED_SETUP(fun setup/0, fun cleanup/1).
... start server here, if any ...
... stop server here, if any ...
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 ...
More information about the erlang-questions