如何模拟任意大小的向量?
How to mock a vector of an arbitrary size?
我定义了一个 class,它接受一个 vector
作为构造函数的输入参数,并提供了一个使用 vector
的 size()
函数的方法:
class Foo {
vector<int> storedVector;
public:
explicit Foo(vector<int>);
bool isSizeGreaterThanInt();
}
Foo::Foo(vector<int> inputVector) : storedVector(std::move(inputVector)) { }
bool Foo::isSizeGreaterThanInt()
{
if (storedVector.size() > INT32_MAX) { return true; }
return false;
}
现在我想测试这个class的isSizeGreaterThanInt()
方法。作为该测试的一部分,我还想验证实现 return 内部的 size()
调用是传递给构造函数的向量的 size()
而不是其他 vector/some其他尺码。
我分别使用 gtest
和 gmock
作为我的测试和模拟框架。
我所有尝试创建 vector<int>
的模拟,将 size()
函数模拟为 return 特定值似乎都失败了,我的模拟的最新版本如下:
template <typename VectorValueType>
class MockVector : public std::vector<VectorValueType> {
public:
MOCK_CONST_METHOD0_T(size, size_t());
};
TEST(Test,TestCase)
{
size_t fakeSize = static_cast<size_t>(INT32_MAX) + 1;
MockVector<int> mockVector;
EXPECT_CALL(mockVector, size()).WillRepeatedly(testing::Return(fakeSize));
size_t testSize = mockVector.size(); // here the value is correct
Foo foo (mockVector);
// if I debug here and check the size of the vector now stored in foo - it's 0.
ASSERT_EQ(true, foo.isSizeGreaterThanInt());
}
我担心 std::move
和移动行为,所以我尝试通过引用传递 inputVector
,尝试传递指针,尝试存储 vector<int>& storedVector
而不是使用值成员...没有成功了。
我想做的事情可行吗?我做错了什么?
更新
其中一位评论者认为这是由于将 MockVector
类型拼接到 vector<int>
中而发生的,并且当它拼接时不再调用模拟方法......但是,我应该如何去嘲笑矢量? C++ STL 中没有 vector<>
的接口,所以我不能将其作为构造函数的参数...
更新 2
正如其中一个答案所建议的那样,是的,我可以在 Foo
中添加一个 getSize()
并模拟它......但它改变了 Foo
的合同并且我' d 不想那样做。此外,如果我愿意这样做,我仍然需要模拟我的 vector
来测试 getSize()
行为,以确保 getSize()
真正 return 是 size()
的矢量,而不是其他一些值。基本上,这样做只是将相同的问题转移到不同的地方。
更新 3
是的,理论上我可以在我的测试中创建一个向量,只是将它传入而不是模拟它。这里的问题是,要测试上述特定行为,我需要创建一个包含 (INT32_MAX + 1
) 元素的 vector
,这对于测试来说非常昂贵 (resources/time/memory) .
您不能模拟 std::vector
的方法,因为 GoogleTest 中的模拟系统基于多态性,并且 std::vector
未准备好用于多态性 - none 它的方法是 virtual
。由于 size()
方法不是 virtual
,因此永远不会调用模拟实现,GoogleMock 无法注册该调用或执行操作。
测试的唯一方法是将大小为 INT32_MAX
的向量传递给被测试的 class(也许这个测试应该默认禁用,只在 CI 中启用envireonment) 或为 std::vector
创建一个包装器,它将在其接口中包含 virtual
方法。
我定义了一个 class,它接受一个 vector
作为构造函数的输入参数,并提供了一个使用 vector
的 size()
函数的方法:
class Foo {
vector<int> storedVector;
public:
explicit Foo(vector<int>);
bool isSizeGreaterThanInt();
}
Foo::Foo(vector<int> inputVector) : storedVector(std::move(inputVector)) { }
bool Foo::isSizeGreaterThanInt()
{
if (storedVector.size() > INT32_MAX) { return true; }
return false;
}
现在我想测试这个class的isSizeGreaterThanInt()
方法。作为该测试的一部分,我还想验证实现 return 内部的 size()
调用是传递给构造函数的向量的 size()
而不是其他 vector/some其他尺码。
我分别使用 gtest
和 gmock
作为我的测试和模拟框架。
我所有尝试创建 vector<int>
的模拟,将 size()
函数模拟为 return 特定值似乎都失败了,我的模拟的最新版本如下:
template <typename VectorValueType>
class MockVector : public std::vector<VectorValueType> {
public:
MOCK_CONST_METHOD0_T(size, size_t());
};
TEST(Test,TestCase)
{
size_t fakeSize = static_cast<size_t>(INT32_MAX) + 1;
MockVector<int> mockVector;
EXPECT_CALL(mockVector, size()).WillRepeatedly(testing::Return(fakeSize));
size_t testSize = mockVector.size(); // here the value is correct
Foo foo (mockVector);
// if I debug here and check the size of the vector now stored in foo - it's 0.
ASSERT_EQ(true, foo.isSizeGreaterThanInt());
}
我担心 std::move
和移动行为,所以我尝试通过引用传递 inputVector
,尝试传递指针,尝试存储 vector<int>& storedVector
而不是使用值成员...没有成功了。
我想做的事情可行吗?我做错了什么?
更新
其中一位评论者认为这是由于将 MockVector
类型拼接到 vector<int>
中而发生的,并且当它拼接时不再调用模拟方法......但是,我应该如何去嘲笑矢量? C++ STL 中没有 vector<>
的接口,所以我不能将其作为构造函数的参数...
更新 2
正如其中一个答案所建议的那样,是的,我可以在 Foo
中添加一个 getSize()
并模拟它......但它改变了 Foo
的合同并且我' d 不想那样做。此外,如果我愿意这样做,我仍然需要模拟我的 vector
来测试 getSize()
行为,以确保 getSize()
真正 return 是 size()
的矢量,而不是其他一些值。基本上,这样做只是将相同的问题转移到不同的地方。
更新 3
是的,理论上我可以在我的测试中创建一个向量,只是将它传入而不是模拟它。这里的问题是,要测试上述特定行为,我需要创建一个包含 (INT32_MAX + 1
) 元素的 vector
,这对于测试来说非常昂贵 (resources/time/memory) .
您不能模拟 std::vector
的方法,因为 GoogleTest 中的模拟系统基于多态性,并且 std::vector
未准备好用于多态性 - none 它的方法是 virtual
。由于 size()
方法不是 virtual
,因此永远不会调用模拟实现,GoogleMock 无法注册该调用或执行操作。
测试的唯一方法是将大小为 INT32_MAX
的向量传递给被测试的 class(也许这个测试应该默认禁用,只在 CI 中启用envireonment) 或为 std::vector
创建一个包装器,它将在其接口中包含 virtual
方法。