В EUnit Erlang утверждает, что функция была вызвана с помощью анонимной функции.

У меня есть код, который выглядит так:

      -module(ca_data).
-export([delete_ca_data/1]).

% ...

delete_ca_data(N) when N < 1 -> ?NEGATIVE_ID_ERROR;
delete_ca_data(N) -> util_db_generic:delete_object(ca_data, N, fun(_) -> ok end).

% ...

И у меня есть тестовый код, который выглядит так:

      wrap_meck(MockMod, MockArgs, F) ->
    meck:new(MockMod, MockArgs),
    try
        F()
    catch Ex ->
        throw(Ex)
    after
        meck:unload(MockMod)
    end.

delete_ca_data_test() ->
    F = fun() ->
        meck:expect(util_db_generic, delete_object, fun (_, _, _) -> ok end),

        ?assertEqual(?NEGATIVE_ID_ERROR, ca_data:delete_ca_data(-1)),

        ?assertEqual([], meck:history(util_db_generic)),

        meck:expect(util_db_generic, delete_object, fun(_, _, _) -> ok end),
        ?assertEqual(ok, ca_data:delete_ca_data(1)),

        ?assertEqual(
            [{self(), {util_db_generic, delete_object, [ca_data, 1, fun(_) -> ok end]}, ok}], % Uh-oh
            meck:history(util_db_generic)
        )
    end,
    wrap_meck(util_db_generic, [], F).

К сожалению, util_db_generic:delete_objectфункция вызывается функцией, созданной в тестируемом модуле.

Это создает некоторые проблемы при попытке подтвердить историю вызовов функций (например, в строке с пометкой «О-о»). Поскольку эта функция создается на месте (а указатель памяти фактически случайный), сложно утверждать, как должна выглядеть эта функция. Этот код не приводит к ошибкам компиляции. Однако утверждения никогда не будут возвращены как действительные, так как две разные функции утверждаются друг против друга (одна создана в ca_dataмодуль и один в тестовом примере). я пытался использовать ?assertMatchи изменение fun(_) -> ok endвыходит за _s, но я получаю эту ошибку компиляции в строке утверждения:

      illegal pattern

Как я могу сопоставить эти результаты?

1 ответ

Хотя документация Erlang обычно хороша, это один из моментов, когда она подводит пользователя. В документации указано :

      Evaluates Expr and matches the result against GuardedPattern, if testing is enabled. ... GuardedPattern can be anything that you can write on the left hand side of the -> symbol in a case-clause, except that it cannot contain comma-separated guard tests.

И документация для состояний :

      Allowed in guard tests.

Тем не менее self()эта функция не может быть использована assertMatchмакрос. Непонятно почему, но эксперимент это доказал.


РЕДАКТИРОВАТЬ 1:

Сюжет закручивается! Когда я редактирую тестовый код, чтобы он выглядел так:

      delete_ca_data_test() ->
    F = fun() ->
        meck:expect(util_db_generic, delete_object, fun (_, _, _) -> ok end),

        ?assertEqual(?NEGATIVE_ID_ERROR, ca_data:delete_ca_data(-1)),

        ?assertEqual([], meck:history(util_db_generic)),

        meck:expect(util_db_generic, delete_object, fun(_, _, _) -> ok end),
        ?assertEqual(ok, ca_data:delete_ca_data(1)),

        Self = self(),

        ?assertEqual(
            [{Self, {util_db_generic, delete_object, [ca_data, 1, _]}, ok}], % Uh-oh
            meck:history(util_db_generic)
        )
    end,
    wrap_meck(util_db_generic, [], F).

код компилируется и работает корректно! Для меня это неожиданный результат! Функция (которую можно использовать в сторожах) не разрешена, но возврат из функции разрешен! Интересно!

Другие вопросы по тегам