在海龟模拟中模拟数组的元素
Mocking elements of an array in turtle mock
我需要在 turtle mock 中模拟数组的元素。不幸的是,因为海龟模拟宏 MOCK_BASE_CLASS
添加了额外的“垃圾”,例如mock::object
、mock::detail::base<>
等,基本类型和模拟类型的大小不再相同。因此,当指向基 class 的指针指向 mock 类型的数组时,指针索引失败,如下所示。
#define BOOST_TEST_MODULE First_TestSuite
#include <boost/test/included/unit_test.hpp>
#include <turtle/mock.hpp>
#include <iostream>
struct Foo
{
int data = 42;
};
MOCK_BASE_CLASS(mockFoo , Foo)
{
};
BOOST_AUTO_TEST_CASE( Demo )
{
mockFoo mf[10];
Foo* b = mf;
std::cout << "b[1].data = " << b[1].data << std::endl;
BOOST_CHECK(b[1].data == 42);
//BOOST_CHECK(sizeof(mockFoo) == sizeof(Foo)); // Also fails. This is the culprit
}
执行输出
Running 1 test case...
b[1].data = 32764
Test047b.cpp(23): error: in "Demo": check b[1].data == 42 has failed
*** 1 failure is detected in the test module "First_TestSuite"
非常感谢有关如何解决此问题的建议。请注意,我无法更改模拟框架并且基类型必须是指针,以便它将指向数组的指针存储到基类型或模拟类型。
更新
下面的例子比较接近我遇到的问题。为了模拟虚函数,使用 MOCK_BASE_CLASS
实际上是不可避免的。我知道问题是将 mockFoo
的 数组 存储为 Foo
。我现在找到了解决方案,我会 post 接受反馈。
struct Foo
{
int value = 42;
int func(){ return value;}
virtual void unused(){}
};
MOCK_BASE_CLASS(mockFoo , Foo)
{
MOCK_METHOD(unused , 0 , void());
};
struct Bar
{
Bar(Foo* f) : foo(f)
{
}
Foo* foo;
};
BOOST_AUTO_TEST_CASE( Demo )
{
mockFoo mf[10];
Bar bar(mf); // uh-oh!
int value = bar.foo[1].func();
std::cout << "bar.foo[1].func() = " << value << std::endl;
BOOST_CHECK(42 == value);
}
结果
Running 1 test case...
bar.foo[1].func() = -960497840
Test047d.cpp(35): error: in "Demo": check 42 == value has failed
*** 1 failure is detected in the test module "First_TestSuite"
如果您查看文档中的 Creation section 并向下滚动一点,您会发现使用 MOCK_BASE_CLASS
宏是可选的,第一个替代方案是继承自 mock::object
手动(这实际上是宏在幕后所做的)。
即使这也不是硬性要求:
Deriving from mock::object is optional but provides the additional following benefits :
- the object acts as a composite to verify and reset all the expectations for all its methods at once
- logs involving the object are enhanced because configuring an expectation for a method will set the class name for all the other methods as well
所以最后你可以做
struct mockFoo : Foo
{
};
但是我不确定你想要实现什么,模拟是关于断言行为(即函数调用)并且通常涉及某种多态性:你的生产代码持有一个指针(或引用)到一个基类型,并且测试将模拟实现替换为生产实现。
我的怀疑得到证实:当数组包含派生 class 类型的对象时,指向基 class 的指针不能用于指针运算 (source)。因此,我创建了一个 wrapper/adapter,我称之为索引器来管理正确类型的索引,如下所示。
struct Foo
{
int value = 42;
int func(){ return value;}
virtual void unused(){}
};
MOCK_BASE_CLASS(mockFoo , Foo)
{
MOCK_METHOD(unused , 0 , void());
};
class FooIndexer
{
public:
typedef Foo& (FooIndexer::*IndexerFunc)(int index);
template<typename T>
FooIndexer(T (&array)[10])
: foo(array)
, indexerFunc( &FooIndexer::indexer<T> )
{
}
template<typename T>
Foo& indexer(int index)
{
T* array = static_cast<T*>(foo);
return array[index];
}
Foo& operator[](int index)
{
return (this->*(indexerFunc))(index);
}
private:
Foo* foo;
IndexerFunc indexerFunc = nullptr;
};
struct Bar
{
template<typename T>
Bar(T (&f)[10]) : foo(f)
{
}
FooIndexer foo;
};
BOOST_AUTO_TEST_CASE( Demo )
{
mockFoo mf[10];
Bar bar(mf);
int value = bar.foo[1].func();
std::cout << "bar.foo[1].func() = " << value << std::endl;
BOOST_CHECK(42 == value);
}
执行输出
Running 1 test case...
bar.foo[1].func() = 42
*** No errors detected
我需要在 turtle mock 中模拟数组的元素。不幸的是,因为海龟模拟宏 MOCK_BASE_CLASS
添加了额外的“垃圾”,例如mock::object
、mock::detail::base<>
等,基本类型和模拟类型的大小不再相同。因此,当指向基 class 的指针指向 mock 类型的数组时,指针索引失败,如下所示。
#define BOOST_TEST_MODULE First_TestSuite
#include <boost/test/included/unit_test.hpp>
#include <turtle/mock.hpp>
#include <iostream>
struct Foo
{
int data = 42;
};
MOCK_BASE_CLASS(mockFoo , Foo)
{
};
BOOST_AUTO_TEST_CASE( Demo )
{
mockFoo mf[10];
Foo* b = mf;
std::cout << "b[1].data = " << b[1].data << std::endl;
BOOST_CHECK(b[1].data == 42);
//BOOST_CHECK(sizeof(mockFoo) == sizeof(Foo)); // Also fails. This is the culprit
}
执行输出
Running 1 test case...
b[1].data = 32764
Test047b.cpp(23): error: in "Demo": check b[1].data == 42 has failed
*** 1 failure is detected in the test module "First_TestSuite"
非常感谢有关如何解决此问题的建议。请注意,我无法更改模拟框架并且基类型必须是指针,以便它将指向数组的指针存储到基类型或模拟类型。
更新
下面的例子比较接近我遇到的问题。为了模拟虚函数,使用 MOCK_BASE_CLASS
实际上是不可避免的。我知道问题是将 mockFoo
的 数组 存储为 Foo
。我现在找到了解决方案,我会 post 接受反馈。
struct Foo
{
int value = 42;
int func(){ return value;}
virtual void unused(){}
};
MOCK_BASE_CLASS(mockFoo , Foo)
{
MOCK_METHOD(unused , 0 , void());
};
struct Bar
{
Bar(Foo* f) : foo(f)
{
}
Foo* foo;
};
BOOST_AUTO_TEST_CASE( Demo )
{
mockFoo mf[10];
Bar bar(mf); // uh-oh!
int value = bar.foo[1].func();
std::cout << "bar.foo[1].func() = " << value << std::endl;
BOOST_CHECK(42 == value);
}
结果
Running 1 test case...
bar.foo[1].func() = -960497840
Test047d.cpp(35): error: in "Demo": check 42 == value has failed
*** 1 failure is detected in the test module "First_TestSuite"
如果您查看文档中的 Creation section 并向下滚动一点,您会发现使用 MOCK_BASE_CLASS
宏是可选的,第一个替代方案是继承自 mock::object
手动(这实际上是宏在幕后所做的)。
即使这也不是硬性要求:
Deriving from mock::object is optional but provides the additional following benefits :
- the object acts as a composite to verify and reset all the expectations for all its methods at once
- logs involving the object are enhanced because configuring an expectation for a method will set the class name for all the other methods as well
所以最后你可以做
struct mockFoo : Foo
{
};
但是我不确定你想要实现什么,模拟是关于断言行为(即函数调用)并且通常涉及某种多态性:你的生产代码持有一个指针(或引用)到一个基类型,并且测试将模拟实现替换为生产实现。
我的怀疑得到证实:当数组包含派生 class 类型的对象时,指向基 class 的指针不能用于指针运算 (source)。因此,我创建了一个 wrapper/adapter,我称之为索引器来管理正确类型的索引,如下所示。
struct Foo
{
int value = 42;
int func(){ return value;}
virtual void unused(){}
};
MOCK_BASE_CLASS(mockFoo , Foo)
{
MOCK_METHOD(unused , 0 , void());
};
class FooIndexer
{
public:
typedef Foo& (FooIndexer::*IndexerFunc)(int index);
template<typename T>
FooIndexer(T (&array)[10])
: foo(array)
, indexerFunc( &FooIndexer::indexer<T> )
{
}
template<typename T>
Foo& indexer(int index)
{
T* array = static_cast<T*>(foo);
return array[index];
}
Foo& operator[](int index)
{
return (this->*(indexerFunc))(index);
}
private:
Foo* foo;
IndexerFunc indexerFunc = nullptr;
};
struct Bar
{
template<typename T>
Bar(T (&f)[10]) : foo(f)
{
}
FooIndexer foo;
};
BOOST_AUTO_TEST_CASE( Demo )
{
mockFoo mf[10];
Bar bar(mf);
int value = bar.foo[1].func();
std::cout << "bar.foo[1].func() = " << value << std::endl;
BOOST_CHECK(42 == value);
}
执行输出
Running 1 test case...
bar.foo[1].func() = 42
*** No errors detected