Как макетировать объекты в 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).
Другие вопросы по тегам