Я хотел бы протестировать метод моей системы, чье возвращаемое значение частично зависит от возвращаемого значения вызова какого-либо интерфейса подключения. В большинстве случаев я бы хотел, чтобы IConnection
возвращал true
при любом вызове этого метода open(_, _)
. За исключением одного случая, когда я явно проверяю состояние при сбое соединения.
Пример:
/*
* Some kind of network interface with method `open`
*/
class IConnection {
public:
IConnection() = default;
virtual ~IConnection() = default;
virtual bool open(const std::string& address, int port) = 0;
};
class ConnectionMock: public IConnection {
public:
MOCK_METHOD2(open, bool(const std::string& address, int port));
};
class MySystem {
public:
MySystem() = delete;
MySystem(std::shared_ptr<IConnection> connection): connection_(connection) {}
bool doSth() {
/*
* Do some things, but fail if connection fails
*/
bool connectionStatus = connection_->open("127.0.0.1", 6969);
if (!connectionStatus) {
return false;
}
// do other things
return true;
}
private:
std::shared_ptr<IConnection> connection_;
};
TEST(MySystemShould, returnFalseIfFailedToOpenConnectionAndTrueIfSucceeded) {
auto connectionMock = std::make_shared<NiceMock<ConnectionMock> >();
ON_CALL(*connectionMock, open(_, _)).WillByDefault(Return(true));
MySystem system(connectionMock);
// if I don't specify Times test fill fail, because WillOnce automatically sets Times(1)
EXPECT_CALL(*connectionMock, open(_, _)).Times(AnyNumber()).WillOnce(Return(false));
/*
* Commented code below is not a good solution - after expectation retires
* the test will fail upon subsequent calls
*/
//EXPECT_CALL(*connectionMock, open(_, _)).WillOnce(Return(false)).RetiresOnSaturation();
ASSERT_FALSE(system.doSth());
/*
* Code bellow allows me to avoid the warning
*/
//EXPECT_CALL(*connectionMock, open(_, _)).WillRepeatedly(Return(true));
ASSERT_TRUE(system.doSth());
}
Проблемы с моим текущим решением состоят в том, что когда переопределение EXPECT_CALL
становится насыщенным, даже если gmock возвращается к действию по умолчанию, указанному в ON_CALL
, каждый последующий вызов open(_, _)
вызывает следующее предупреждение:
GMOCK WARNING:
/whatever.cpp:105: Actions ran out in EXPECT_CALL(*connectionMock, open(_, _))...
Called 2 times, but only 1 WillOnce() is specified - taking default action specified at:
/whatever.cpp:103:
хотя я использую NiceMock
. Я могу избавиться от предупреждения, указав EXPECT_CALL
с помощью WillRepeatedly(Return(true))
, но это дублирование моего кода в ON_CALL
.
Я хотел бы знать, как я могу переопределить действие по умолчанию, указанное в ON_CALL
, только для одного вызова IConnection::open
, а затем вернуться к значениям по умолчанию, не заставляя gmock печатать предупреждение. Идеальным решением будет что-то похожее на:
EXPECT_CALL(*connectionMock, open(_, _)).WillOnce(Return(false)).DisableExpectationAfterSaturation();
но его не существует. RetiresOnSaturation
не работает так, как мне хотелось бы, потому что он не проходит тест после насыщения (не соответствует действию, указанному в ON_CALL
).