c++ - GoogleMock:如何保存要在模拟的下一次调用中使用的参数
问题描述
我尝试模拟代表 NVRAM 的现有类的行为和 API。API 是:
bool Init(Uint8* dataPointer);
bool Store(); //Writes the data from dataPointer into the NVRAM
bool Restore(); //Writes the data from NVRAM into the dataPointer
我的测试场景如下:
创建
ClassUnderTest
,也调用Init
方法在 my 中调用另一个方法
ClassUnderTest
,该方法调用Restore
-method。而且我希望能够以某种方式控制我的模拟,即在调用Restore
-method之后dataPointer
设置的值。
或者在伪代码中:
MockFoo foo;
EXPECT_CALL(foo, Init(dataPointer)).WillOnce(Return(true));
EXPECT_CALL(foo, Restore()).WillOnce(DoAll(memcpy(dataPointer, testValues, sizeOf(testValues)), Return(true)));
到目前为止我已经尝试过:
- 来自 googleMock 的默认操作(例如 SaveArg):允许我将数据写入
dataPointer
,但仅限于Init
-call。 - 编写 ACTION_TEMPLATE 以将其保存
dataPointer
在 lokal 变量中,然后在Restore
调用时更改其值:据我所知,我只能将 VALUE_PARAMS 添加到 ACTION_TEMPLATE,因此我可以将值传递到模板中,但无法将它们传递出去再次通过一些指针。 - 我查看了 ActionInterface & Polymorphic Actions,如果我正确理解了文档,它们与 ACTION_TEMPLATE 具有相同的限制,关于我的问题。
最后对我来说主要问题是:有没有办法在 -calldataPointer
期间保存Init
以供以后使用?
解决方案
SaveArg
就我个人而言,我几乎从不使用 thisACTION
或其他小的 gmock 功能。我更喜欢使用Invoke
并定义我自己的逻辑,每当调用模拟方法时都应该调用它。它可能看起来有点矫枉过正,但实际上通常更具可读性和更短:
class API {
public:
virtual bool Init(uint8_t* dataPointer) = 0;
virtual bool Store() = 0;
virtual bool Restore() = 0;
};
class MockAPI : public API {
public:
MOCK_METHOD1(Init,
bool(uint8_t* dataPointer));
MOCK_METHOD0(Store,
bool());
MOCK_METHOD0(Restore,
bool());
};
class ClassUnderTest {
public:
explicit ClassUnderTest(std::shared_ptr<API> api): api_(api) {
dataPtr_ = new uint8_t;
api_->Init(dataPtr_);
}
~ClassUnderTest() {
delete dataPtr_;
}
bool anotherMethod() {
api_->Restore();
return true;
}
uint8_t takeALookAtTheData() {
return *dataPtr_;
}
private:
std::shared_ptr<API> api_;
uint8_t* dataPtr_;
};
using testing::_;
using testing::Invoke;
TEST(xxx, yyy) {
auto mockApi = std::make_shared<MockAPI>();
uint8_t* dataPtr(nullptr);
uint8_t testValue = 123;
ON_CALL(*mockApi, Init(_)).WillByDefault(Invoke([&dataPtr](uint8_t* dataPointer) {
dataPtr = dataPointer;
return true;
}));
ON_CALL(*mockApi, Restore()).WillByDefault(Invoke([&dataPtr, testValue]() {
*dataPtr = testValue;
return true;
}));
ClassUnderTest sut(mockApi);
ASSERT_NE(nullptr, dataPtr);
sut.anotherMethod();
ASSERT_EQ(testValue, *dataPtr);
ASSERT_EQ(testValue, sut.takeALookAtTheData());
}
我希望我假设正确,您的系统应该分配所需的内存,而您的 API 负责操作它。无论如何,这应该可以解决您的问题。
推荐阅读
- clojure - 使用循环重复计算胜率
- javascript - 正则表达式,匹配所有内容,除了双星号
- r - 使用 `stringr` 删除列名中的异常字符
- java - Maven:无法将资源复制到远程目录
- python - Replace dictionary values with a list
- java - 减少方法中的冗余
- c++ - 停止后恢复完成端口通知
- r - 在 dplyr 中构建动态行数的总和
- linux - java.lang.IllegalArgumentException 错误取决于使用的符号名称 - Clojure
- c++ - Catch2 cmake 函数 'catch_discover_tests()' 在 bulid 时间不起作用