Как макетировать объекты в Erlang, используя Meck?
Хорошо, я использую Мек, и я потерян. Мой первый язык (который я пишу около 7 месяцев) - это Ruby, так что я пока не могу обернуться вокруг насмешек над Меком. Я, правда, насмехаюсь над Руби. Надеюсь, кто-то может мне помочь. Кроме того, я пишу Эрланг только неделю.
Обновленный код (но издевательство все еще не работает)...
У меня есть модуль суфлера Erlang console_io, который выглядит следующим образом:
-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]).
Мой тест теперь выглядит так:
-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).
Я получаю ошибку:
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
Я хочу смоделировать (заглушка?) Функцию get в моем тесте, чтобы get возвращал "aaaa", а затем, когда я утверждаю get_guess(), он должен быть равен ["a", "a", "a", "a" ].
Как мне это сделать?
2 ответа
Есть две проблемы:
prompter
Модуль имеет две экспортированные функции, но вы только издеваетесь над одной из них (gets
) сmeck:expect
, По умолчанию Мекк создает новый модуль, который содержит только те функции, которые вы явно насмехаетесь. Вы можете изменить это, используяpassthrough
опция:meck:new(prompter, [passthrough]),
Когда вы издеваетесь
gets
функция, все вызовы с префиксом модуля (т.е.prompter:gets()
) перехватываются, но Мек не имеет возможности (пока?) перехватывать внутренние вызовы (например,gets()
позвонить вguess
функция), так что вы все равно получите unmocked версию функции. Не существует полностью удовлетворительного способа избежать этого. Вы можете изменить вызов вguess
вprompter:gets()
или вы могли бы двигатьсяgets
в отдельный модуль и высмеивать это.
Первая строка говорит о создании нового макета модуля, my_library_module
:
meck:new(my_library_module),
Далее мы издеваемся над функцией fib
в my_library_module
вернуть 21, когда 8 передается в:
meck:expect(my_library_module, fib, fun(8) -> 21 end),
У нас есть несколько утверждений eunit для проверки нашей фиктивной функции. code_under_test:run
Вызовите то, что вы хотите заменить на функцию, используя ваш смоделированный модуль, и 21
результат, который вы ожидаете от вызова функции:
?assertEqual(21, code_under_test:run(fib, 8)), % Uses my_library_module
?assert(meck:validate(my_library_module)),
Затем выгрузим проверенный модуль:
meck:unload(my_library_module).
Если вы хотите написать такой же тест для вашего модуля, вы можете написать:
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).