Okay, I'm using Meck and I'm lost. My first language (that I've been writing for about 7 months) is Ruby, so I can't seem to wrap my brain around Meck mocking yet. I do get Ruby mocking though. Hoping someone can help me. Also, I've only been writing Erlang for a week.
Updated Code (but mocking still isn't working)...
I have a Erlang console_io prompter module that looks like this:
-module(prompter).
-export([prompt/1, guess/0]).
prompt(Message) ->
console_io:gets(Message).
gets() ->
{_, [Input]} = io:fread("Enter: ", "~s"),
Input.
guess() ->
Guess_Input = gets(),
Guess_List = convert_guess_to_list(Guess_Input).
convert_guess_to_list(Guess_Input) ->
re:split(Guess_Input, "", [{return, list}, trim]).
My test now looks like this:
-module(prompter_test).
-include_lib("eunit/include/eunit.hrl").
guess_1_test() ->
meck:new(prompter),
meck:expect(prompter, gets, fun() -> "aaaa" end),
?assertEqual(prompter:guess(), ["a","a","a","a"]),
?assert(meck:validate(prompter)),
meck:unload(prompter).
The error I'm getting is this:
Eshell V5.9.3.1 (abort with ^G)
1> prompter_test: guess_1_test (module 'prompter_test')...*failed*
in function prompter:guess/0
called as guess()
in call from prompter_test:guess_1_test/0 (test/prompter_test.erl, line 10)
in call from prompter_test:guess_1_test/0
**error:undef
I want to mock (stub?) the gets function in my test so that gets will return "aaaa" and then when I assert on get_guess() it should equal ["a", "a", "a", "a"].
How do I do this?
There are two problems:
The prompter
module has two exported functions, but you only mock one of them (gets
) with meck:expect
. By default, Meck creates a new module that only contains the functions that you explicitly mock. You can change that by using the passthrough
option:
meck:new(prompter, [passthrough]),
When you mock the gets
function, all module-prefixed calls (i.e. prompter:gets()
) are intercepted, but Meck has no way (yet?) of intercepting internal calls (e.g. the gets()
call in the guess
function), so you would still get the unmocked version of the function. There is no completely satisfactory way to avoid this. You could change the call in guess
to prompter:gets()
, or you could move gets
into a separate module and mock that.
The first line says to create a new mocked module, my_library_module
:
meck:new(my_library_module),
Next, we mock the function fib
in my_library_module
to return 21 when 8 is passed in:
meck:expect(my_library_module, fib, fun(8) -> 21 end),
We have some eunit assertions to test our mocked function. The code_under_test:run
call is what you want to replace with the the function using your mocked module, and the 21
is the result you are expecting from the function call:
?assertEqual(21, code_under_test:run(fib, 8)), % Uses my_library_module
?assert(meck:validate(my_library_module)),
Then we unload the mocked module:
meck:unload(my_library_module).
If you wanted to write the same test for your module, you could write:
my_test() ->
meck:new(console_io),
meck:expect(console_io, gets, fun() -> "aaaa" end),
?assertEqual(["a", "a", "a", "a"], console_io:get_guess()), % Uses console_io
?assert(meck:validate(console_io)),
meck:unload(console_io).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With