我尝试模拟代表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
方法
在我的ClassUnderTest
中调用另一个方法,该方法调用Restore
方法。而且我希望能够以某种方式控制我的模拟,在调用Restore
方法之后,设置dataPointer
的值。
或使用伪代码:
MockFoo foo;
EXPECT_CALL(foo, Init(dataPointer)).WillOnce(Return(true));
EXPECT_CALL(foo, Restore()).WillOnce(DoAll(memcpy(dataPointer, testValues, sizeOf(testValues)), Return(true)));
到目前为止,我已经尝试过:
dataPointer
,但只能进行Init
通话。dataPointer
保存在一个lokal变量中,然后在调用Restore
时更改其值:据我所知,我只能将VALUE_PARAMS添加到ACTION_TEMPLATEs中,这样我就可以值添加到模板中,但是无法将它们再次通过某个指针分发出去。最后,对我来说,主要问题是:
有没有一种方法可以在dataPointer
通话期间保存Init
以便以后使用?
答案 0 :(得分:2)
我个人几乎从未使用过此SaveArg
,ACTION
或其他小型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负责操纵它。无论如何,这应该可以解决您的问题。