我有一个函数需要一个我正在嘲笑的 const void* 。我想要基于传递到函数中的指针值的匹配器。
例如:
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
class A
{
public:
A(std::vector<uint32_t> data) : m_data(data) {}
void doSomething()
{
for (auto x : data)
writeData(&x, sizeof(x))
}
void writeData(const void* val, size_t size)
{
//More complicated than that obviously
std::cout << "Writing data" << std::endl;
}
private:
std::vector<uint32_t> m_data;
};
class MockA : public A
{
public:
MOCK_METHOD(void, writeData, (const void* val, size_t size));
}
TEST(TestA, writeData)
{
std::vector<uint32_t> testData{1,2,3,4};
MockA myMockObj (testData);
uint32_t expVal1 = 1;
uint32_t expVal2 = 2;
uint32_t expVal3 = 3;
uint32_t expVal4 = 4;
//The problem is the matcher won't work because writeData takes const void*
//Pointer comparison doesn't work because the pointers dont't point to the same obj
//for example &testData[1] != m_data[1] and also (void*)&expVal2 != val
EXPECT_CALL(myMockObj, writeData(expVal4, 4)).Times(1);
EXPECT_CALL(myMockObj, writeData(expVal3, 4)).Times(1);
EXPECT_CALL(myMockObj, writeData(expVal2, 4)).Times(1);
EXPECT_CALL(myMockObj, writeData(expVal1, 4)).Times(1);
myMockObj.doSomething();
}
我想要一个根据两个参数的值进行匹配的匹配器,如上例所示。 问题是第一个参数是 void* 而不是 uint32_t。
我无法进行指针比较,因为参数和我要匹配的内容位于不同的内存位置。
我发现这个讨论这似乎表明我将无法使用 SaveArgPointee 副作用。我确实尝试了一些类似的事情:
uint32_t testData = 50;
uint32_t actualData;
EXPECT_CALL(myMockObj, writeData(testing::_, 4)).Times(1).WillOnce(testing::SaveArgPontee<0>(&actualData));
抱怨
const void* is not a pointer-to-oject type
然后我尝试像这样写我自己的动作
ACITON_P(AssignVoidPtr, param) {param = * (const_cast<uint32_t*>(static_cast<const unit32_t*>(arg0))); }
才发现参数不可写
我尝试使用间接方法,通过另一个自定义操作返回指针的值:
ACITON(AssignVoidPtr) { return * (const_cast<uint32_t*>(static_cast<const unit32_t*>(arg0))); }
class MockA : public A
{
public:
MOCK_METHOD(uint32_t, dummy, (const void* val, size_t size));
void writeData(conts void* val, size_t size)
{
dummy(val, size)
}
}
TEST(TestA, writeData)
{
std::vector<uint32_t> testData{1,2,3,4};
MockA myMockObj (testData);
uint32_t expVal1 = 1;
uint32_t expVal2 = 2;
uint32_t expVal3 = 3;
uint32_t expVal4 = 4;
uint32_t actVal1;
uint32_t actVal2;
uint32_t actVal3;
uint32_t actVal4;
//In the actual test I can differentiate between the expect calls so the correct value is assigned to each var
actVal4 = EXPECT_CALL(myMockObj, dummy(testing::_, 4)).Times(4).WillOnce(AssignVoidPtr());
actVal3 = EXPECT_CALL(myMockObj, dummy(testing::_, 4)).Times(1).WillOnce(AssignVoidPtr());
actVal2 = EXPECT_CALL(myMockObj, dummy(testing::_, 4)).Times(1).WillOnce(AssignVoidPtr());
actVal1 = EXPECT_CALL(myMockObj, dummy(testing::_, 4)).Times(1).WillOnce(AssignVoidPtr());
ASSERT_EQ(data[0], actVal1);
myMockObj.doSomething();
}
但是上面给出了一个错误,它无法在 fake_type 和 uint32_t 之间转换
知道如何实现这一目标吗?
修复了类定义中的一些编译器错误后,解决方案是:
#include <vector>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
class A {
public:
A(std::vector<uint32_t> data) : m_data(data) {}
void doSomething() {
for (auto x : m_data)
writeData(&x, sizeof(x));
}
virtual void writeData(const void* val, size_t size) {}
private:
std::vector<uint32_t> m_data;
};
class MockA : public A {
public:
using A::A;
MOCK_METHOD(void, writeData, (const void* val, size_t size), (override));
};
TEST(TestA, writeData) {
using ::testing::Eq;
using ::testing::Pointee;
using ::testing::SafeMatcherCast;
std::vector<uint32_t> testData{1, 2};
MockA myMockObj(testData);
EXPECT_CALL(myMockObj,
writeData(MatcherCast<const void*>(
SafeMatcherCast<const uint32_t*>(Pointee(Eq(1)))),
sizeof(uint32_t)));
EXPECT_CALL(myMockObj,
writeData(MatcherCast<const void*>(
SafeMatcherCast<const uint32_t*>(Pointee(Eq(2)))),
sizeof(uint32_t)));
myMockObj.doSomething();
}