0

我需要在海龟模拟中模拟数组的元素。不幸的是,因为turtle mock 宏MOCK_BASE_CLASS添加了额外的“gunk”,例如mock::objectmock::detail::base<>等等,基本类型和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为了模拟虚拟功能,使用实际上是不可避免的。我知道问题在于存储as的数组。我现在找到了一个解决方案,我将根据反馈发布。mockFooFoo

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"
4

2 回答 2

1

如果您查看文档中的“创建”部分并向下滚动一点,您会发现使用MOCK_BASE_CLASS宏是可选的,第一种选择是mock::object手动继承(实际上是宏在引擎盖下所做的)。

甚至这也不是硬性要求:

从 mock::object 派生是可选的,但提供以下额外好处:

  • 该对象作为一个复合体来一次验证和重置其所有方法的所有期望
  • 涉及对象的日志得到了增强,因为为方法配置期望也会为所有其他方法设置类名

因此,最后你可以做

struct mockFoo : Foo
{
};

但是我不确定您要实现什么,模拟是关于断言行为(即函数调用)并且通常涉及某种多态性:您的生产代码包含指向基本类型的指针(或引用),并且测试将模拟实现替换为生产实现。

于 2021-03-13T09:08:49.850 回答
0

我的怀疑得到了证实:当数组包含派生类类型(source的对象时,指向基类的指针不能用于指针算术。因此,我创建了一个包装器/适配器,我称之为 indexer 来管理正确类型的索引,如下所示。

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
于 2021-03-15T00:15:53.597 回答