GMock — возвращает значение по умолчанию с ON_CALL для перегруженных методов

Я пытаюсь написать макет для класса, который содержит три перегруженных метода, т.е.

#include <gtest/gtest.h>
#include <gmock/gmock.h>

using ::testing::_;
using ::testing::Return;
using ::testing::A;
using ::testing::ByRef;
using ::testing::Ref;
using ::testing::TypedEq;

struct Foo {
int fooMethod(const int& intParam) { return 0; }
int fooMethod(const float& floatParam) { return 0; }
int fooMethod(const std::string& stringParam) { return 0; }
};

struct FooMock {
FooMock() {
ON_CALL(*this, fooMethod(_)).WillByDefault(Return(-1));
}

MOCK_METHOD1(fooMethod, int(const int& intParam));
MOCK_METHOD1(fooMethod, int(const float& floatParam));
MOCK_METHOD1(fooMethod, int(const std::string& stringParam));
};

но это дает ошибку:

 error: call of overloaded ‘gmock_fooMethod(const testing::internal::AnythingMatcher&)’ is ambiguous

Я также попробовал TypedEq () вместо «_», но это дает больше неясных ошибок. Я проверил GMock FAQ, Wiki и не нашел решения — как я могу вернуть значение по умолчанию с ON_CALL для перегруженных методов?

BR,
Лукаш

6

Решение

У @ tx34 есть суть ответа, но в коде есть еще несколько проблем.

Во-первых, документы по Выбор между перегруженными функциями являются наиболее подходящими. У вас есть три перегрузки fooMethod с одинаковым количеством аргументов, но с разными типами аргументов. Вам нужно будет использовать средство сопоставления, которое определяет тип.

Далее вам нужно определить все ваши Foo функции, которые должны быть смоделированы как virtualили же вызывать их через Foo объект не будет вызывать производные фиктивные функции. Так как вы определяете Foo как базовый класс, он также должен иметь виртуальный деструктор, чтобы избежать нарезки.

Наконец, вам нужно иметь FooMock наследовать от Foo,

Итак, собрав все это, вы получите что-то вроде:

#include <memory>
#include <string>
#include "gtest/gtest.h"#include "gmock/gmock.h"
using ::testing::_;
using ::testing::An;
using ::testing::Matcher;
using ::testing::TypedEq;
using ::testing::Return;

struct Foo {
virtual ~Foo() {}
virtual int fooMethod(const int&) { return 0; }
virtual int fooMethod(const float&) { return 0; }
virtual int fooMethod(const std::string&) { return 0; }
};

struct FooMock : Foo {
FooMock() : Foo() {
ON_CALL(*this, fooMethod(An<const int&>())).
WillByDefault(Return(-1));
ON_CALL(*this, fooMethod(Matcher<const float&>(_))).
WillByDefault(Return(-2));
ON_CALL(*this, fooMethod(TypedEq<const std::string&>("1"))).
WillByDefault(Return(-3));
}

MOCK_METHOD1(fooMethod, int(const int& intParam));
MOCK_METHOD1(fooMethod, int(const float& floatParam));
MOCK_METHOD1(fooMethod, int(const std::string& stringParam));
};

TEST(Foo, foo) {
std::shared_ptr<Foo> foo(new FooMock);
auto foo_mock(std::dynamic_pointer_cast<FooMock>(foo));

EXPECT_CALL(*foo_mock, fooMethod(Matcher<const int&>(_))).Times(1);
EXPECT_CALL(*foo_mock, fooMethod(Matcher<const float&>(_))).Times(1);
EXPECT_CALL(*foo_mock, fooMethod(Matcher<const std::string&>(_))).Times(1);

EXPECT_EQ(-1, foo->fooMethod(1));
EXPECT_EQ(-2, foo->fooMethod(1.0f));
EXPECT_EQ(-3, foo->fooMethod("1"));
}int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
10

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

Проблема в том, что TypedEq ожидает значения, а не совпадения. Вы можете достичь того, что вы хотите, путем:

ON_CALL(*this, fooMethod(An<ArgType>())).WillByDefault(Return(-1));

или же

ON_CALL(*this, fooMethod(Matcher<ArgType>(_))).WillByDefault(Return(-1));

Смотрите также:

https://github.com/google/googletest/blob/master/googlemock/docs/CookBook.md#selecting-between-overloaded-functions

https://github.com/google/googletest/blob/master/googlemock/docs/CheatSheet.md#wildcard

https://github.com/google/googletest/blob/master/googlemock/docs/CheatSheet.md#generic-comparison

2

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