[erlang-questions] Mocking I/O calls - defining sequence of returns

Tim Watson <>
Mon May 23 11:21:39 CEST 2011


> On May 22, 2011 2:40 AM, "Alyssa Kwan" <> wrote:
>> I'm sorry, I wasn't being specific. Is there any way to mock a sequence of
>> calls to the same function? Like if I call io:get_line (or a wrapper because
>> it's protected), how do I get it to return a different value for the first
>> call and the second call?
>>
>> Also, will it expect exactly two calls as well? And does meck record call
>> order for different functions?

I believe that meck preserves the call order and there is an API call
to get back the call "history" as well - meck:history(Mod). As Tobias
has pointed out, erlymock will do this for you too. If you're
interested in tracking complex state in, say, a gen_server, there is
also https://github.com/noss/emock which can be combined with other
libraries to good effect. I'd also suggest looking at the statem
functionality in either QuickCheck (http://www.quviq.com/) or
https://github.com/manopapad/proper for complex cases. All of these
can be combined with convenience libraries like
https://github.com/hyperthunk/hamcrest-erlang if you want to sprinkle
a little sugar on your test code!

Here's a (somewhat contrived) example of what you want to do with meck:

:~ $ erl
Erlang R14B01 (erts-5.8.2) [source] [64-bit] [smp:2:2] [rq:2]
[async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.2  (abort with ^G)
1> code:unstick_mod(io).
true
2> meck:new(io, [passthrough]).
ok
3> meck:expect(io, get_line, 1, "hello world!").
ok
4> io:get_line(prompt).
"hello world!"
5>
5> meck:expect(io, get_line,
5>     fun(name) -> "Joe Bloggs";
5>        (Other) -> meck:passthrough([Other])
5>     end).
ok
6> io:get_line(name).
"Joe Bloggs"
7> io:get_line(other).
other
"\n"
8> meck:unload(io).
ok
9> meck:new(io, [passthrough]).
ok
10> meck:expect(io, format, 2, "always return this").
ok
11> io:format("123 ~p~n", [hello]).
"always return this"
12> io:format("123 ~p~n", [world]).
"always return this"
13> WasPassedToIO = fun(X) -> lists:keymember({io, format, X}, 1,
meck:history(io)) end.
#Fun<erl_eval.6.13229925>
14> hamcrest:assert_that(["123 ~p~n",[hello]], WasPassedToIO, fun() ->
meck:unload(io) end).
true
15>

Or in a test module:

-module(mytests).
-include_lib("hamcrest/include/hamcrest.hrl").

passed_to_io() ->
    fun(X) -> lists:keymember({io, format, X}, 1, meck:history(io)) end.

mytest() ->
    %% setup code, e.g., meck:new(....), meck:expect(...) ,etc
    ?assertThat(["123 ~p~n",[hello]], passed_to_io()).



More information about the erlang-questions mailing list