HippoMocks — Использование & quot; ExpectCallFunc & quot; после & quot; NeverCallFunc & quot; одна и та же функция приводит к неожиданному & quot; HippoMocks :: ExpectationException & quot;

Представьте, что у нас есть модульный тест, который сначала выполняет последовательность кода, для которой мы ожидаем функцию someFunc не вызывается, затем выполняет последовательность кода, для которой мы ожидаем, что эта функция будет вызвана ровно один раз. С помощью HippoMocks, мы могли бы написать это так:

#include <hippomocks.h>

void someFunc (void)
{

}

int main (int argc, char ** argv)
{
MockRepository mocks;
mocks.autoExpect = false;

mocks.NeverCallFunc(someFunc); // line 27

/* some testing code ... */

/* ... in the course of which someFunc does not get called ... */

mocks.ExpectCallFunc(someFunc); // line 33

/* other testing code ... */
someFunc();
/* ... in the course of which someFunc got called */

return 0;
}

Однако при запуске приведенного выше фрагмента в Windows (скомпилированного с помощью набора инструментов Cygwin) HippoMocks::ExpectationException брошен:

terminate called after throwing an instance of 'HippoMocks::ExpectationException'
what():  Function someFunc() called with mismatching expectation!
Expectations set:
../main.cpp(33) Expectation for someFunc() on the mock at 0x0 was not satisfied.
Functions explicitly expected to not be called:
../main.cpp(27) Result set for someFunc() on the mock at 0x0 was used.

Так что мне интересно …

… (1), если HippoMocks не предназначен для обработки такого сценария. Ожидает ли это someFunc вызывается (строка 33) не заменяет предыдущее ожидание в соответствующем репозитории?

… (2), почему второе ожидание (строка 33) не было удовлетворено, так как someFunc явно вызывается. Если таковые имеются, я ожидал бы, что первое ожидание (строка 27) не будет выполнено?

Интересно, что все работает наоборот. Следующий фрагмент кода работает без проблем:

#include <hippomocks.h>

void someFunc (void)
{

}

int main (int argc, char ** argv)
{
MockRepository mocks;
mocks.autoExpect = false;

mocks.ExpectCallFunc(someFunc); // line 27

/* some testing code ... */
someFunc();
/* ... in the course of which someFunc got called */

mocks.NeverCallFunc(someFunc); // line 33

/* other testing code ... */

/* ... in the course of which someFunc does not get called ... */

/* someFunc(); */

return 0;
}

Более того, если вызов someFunc вставляется после второго ожидания во втором фрагменте (как указано в комментарии), это обнаруживается и сообщается HippoMocks как ожидание «никогда не вызывать», как и следовало ожидать:

terminate called after throwing an instance of 'HippoMocks::ExpectationException'
what():  Function someFunc() called with mismatching expectation!
Expectations set:
../main.cpp(27) Expectation for someFunc() on the mock at 0x0 was satisfied.
Functions explicitly expected to not be called:
../main.cpp(33) Result set for someFunc() on the mock at 0x0 was used.

Любая помощь эксперта HippoMocks будет оценена …

2

Решение

Вы не можете этого сделать, потому что NeverCall предназначен для того, чтобы генерировать исключение для утверждения.
Кажется совершенно нелогичным для меня.

Если вы действительно хотите обойти это, настройте следующее

mocks.OnCallFunc(someFunc).Do(someFuncCalledHandler);

В вашем собственном обработчике вы можете реализовать необходимую логику:

bool callAllowed = true; //global variable
void someFuncCalledHandler()
{
if (!callAllowed)
{
throw MyNeverCallException();
}
}

В своем тесте вы можете управлять поведением someFuncCalledHandler ():

callAllowed = false;
someFunc();

Кстати: плохая идея смешивать компоновку и код действия в тесте, как вы делали в своем примере кода

1

Другие решения

Ожидания Hippomocks проверяются либо когда MockRepositoryдеструктор называется или когда его VerifyAll() Метод явно вызывается. Вызов VerifyAll() до строки 33 и ваш первый пример будет работать нормально.

Я повторяю предыдущий ответ, что тестовый код и тестируемый код не следует смешивать, но я могу представить, что это только ради компактного вопроса.

1

Взаимодействие между NeverCall а также ExpectCall не был действительно продуман прежде — я никогда не ожидал, что люди будут использовать NeverCall вообще много, так что я не понял взаимодействия.

В текущей выпущенной версии NeverCall получит автоэксперту на предыдущей ExpectCall, и все NeverCalls будет проверен первым. Это приводит к ExpectCall/NeverCall работать, как ожидалось — то есть, вы сначала получите ожидание, а затем NeverCall активен В случае NeverCall/ExpectCall нет autoexpects добавляются и NeverCall получает приоритет. Это нелогично, и я думаю, что лучше поменять поведение, чтобы ExpectCalls всегда получают приоритет, если они могут совпадать.

Я добавил ваш пример в качестве нового теста & поменял местами порядок совпадений NeverCall а также ExpectCall, Я также удалил autoExpect за NeverCallс — потому что этого не должно было быть в первую очередь. В результате оба ваших примера теперь будут работать так, как вы ожидаете, autoExpect вкл или выкл. Ваш второй пример будет также работать, если someCall после NeverCall настроен. Это позволяет вам группировать ваш установочный код больше, чем раньше.

Если вы хотите проверить / переключиться на эту версию, обратите внимание, что она все еще находится в ветке cpp11. Я объединю это с мастером & отпустить, когда ветка подтвердится стабильной & документация должным образом расширена. В настоящее время нет известных проблем с ним. Это на Github: https://github.com/dascandy/hippomocks/tree/cpp11 .

0
По вопросам рекламы [email protected]