Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何模拟方法返回已删除副本的对象?_C++_Unit Testing_Googletest_Gmock - Fatal编程技术网

C++ 如何模拟方法返回已删除副本的对象?

C++ 如何模拟方法返回已删除副本的对象?,c++,unit-testing,googletest,gmock,C++,Unit Testing,Googletest,Gmock,如果一个接口有一个函数来创建一个具有已删除副本的对象,如何模拟该函数? Gmock似乎在内部使用对象的复制构造函数 例如 编译错误显示: gmock/gmock-spec-builders.h:1330:20: error: use of deleted function 'TTest::TTest(const TTest&)' T retval(value_); ... gmock/gmock-actions.h:190:52: error: use of deleted f

如果一个接口有一个函数来创建一个具有已删除副本的对象,如何模拟该函数? Gmock似乎在内部使用对象的复制构造函数

例如

编译错误显示:

gmock/gmock-spec-builders.h:1330:20: error: use of deleted function 'TTest::TTest(const TTest&)'
     T retval(value_);
...
gmock/gmock-actions.h:190:52: error: use of deleted function 'TTest::TTest(const TTest&)'
         internal::BuiltInDefaultValue<T>::Get() : *value_;
...
gmock/internal/gmock-internal-utils.h:371:71: error: use of deleted function 'TTest::TTest(const TTest&)'
       *static_cast<volatile typename remove_reference<T>::type*>(NULL));
gmock/gmock spec builders.h:1330:20:错误:使用了已删除的函数'TTest::TTest(const-TTest&)'
T retval(值u);
...
gmock/gmock actions.h:190:52:错误:使用已删除的函数“TTest::TTest(const TTest&)”
内部::内置indefaultvalue::Get():*值;
...
gmock/internal/gmock internal utils.h:371:71:错误:使用已删除的函数“TTest::TTest(const TTest&)”
*静态_cast(NULL));
如果该方法返回
std::unique_ptr
,则错误相同,因为
std::unique_ptr
也删除了复制ctor

因此,我的问题是:如何模拟这些返回带有已删除副本的对象的方法


我正在使用googletestv1.7、GCC 5.3.0和Ubuntu 14.04.1。

正如在评论中提到的,Google Test 1.8似乎支持模拟这些功能()

至于1.7,我找到了一个解决方案

首先,创建一个实用程序类来包装不可复制的对象:

template <typename T>
class Mover
{
public:
    Mover(T&& object)
      : object(std::move(object)),
        valid(true)
    {
    }

    Mover(const Mover<T>& other)
      : object(const_cast<T&&>(other.object)),
        valid(true)
    {
        assert(other.valid);
        other.valid = false;
    }

    Mover& operator=(const Mover& other)
    {
        assert(other.valid);
        object = const_cast<T&&>(other.object);
        other.valid = false;
        valid = true;
    }

    T& get()
    {
        assert(valid);
        return object;
    }

    const T& get() const
    {
        assert(valid);
        return *object;
    }

private:
    T object;
    mutable bool valid;
};

template <typename T>
inline Mover<T> Movable(T&& object)
{
    return Mover<T>(std::move(object));
}
模板
班级搬运工
{
公众:
移动器(T&对象)
:对象(标准::移动(对象)),
有效(真)
{
}
移动器(固定移动器和其他)
:object(const_cast(other.object)),
有效(真)
{
断言(其他有效);
other.valid=false;
}
移动器和操作员=(常量移动器和其他)
{
断言(其他有效);
object=const_cast(other.object);
other.valid=false;
有效=真;
}
T&get()
{
断言(有效);
返回对象;
}
常量T&get()常量
{
断言(有效);
返回*对象;
}
私人:
T对象;
可变布尔有效;
};
模板
内联移动器(T&&object)
{
返回移动器(std::move(object));
}
然后创建一个代理模拟:

class MockMyInterface : public MyInterface
{
public:
    MOCK_METHOD0(GetUniqueTest_, Mover<TTest>());
    TTest GetUniqueTest()
    {
        return std::move(GetUniqueTest_().get());
    }
}
class MockMyInterface:公共MyInterface
{
公众:
MOCK_方法0(GetUniqueTest_,Mover());
测试GetUniqueTest()
{
返回std::move(GetUniqueTest_uz().get());
}
}

在这里回答我自己的问题只是为了提供最新信息

在googletest1.8.0版或更高版本中,它引入了
ByMove(…)
,并且本机仅支持返回移动类型

因此,代码编译正常:

class MockMyInterface: public MyInterface{
    public:
        MOCK_METHOD0(GetUniqueTest, TTest());
}
但在运行时它抛出异常,因为gmock不知道如何返回默认值
TTest

C++ exception with description "Uninteresting mock function call - returning default value.
    Function call: GetUniqueTest()
    The mock function has no default action set, and its return type has no default value set." thrown in the test body.
这可以通过在模拟类中设置默认操作轻松解决:

ON_CALL(*this, GetUniqueTest()).WillByDefault(Return(ByMove(TTest(0))));
注意:对于
std::unique_ptr
,它没有问题,因为它有默认构造函数,默认情况下会返回
nullptr
unique_ptr

综上所述,如果使用googletest1.8.0或更高版本,我们可以:

// My interface to mock
class MyInterface
{
    public:
        virtual ~MyInterface() {}
        virtual TTest GetUniqueTest() = 0;
        virtual std::unique_ptr<int> GetUniqueInt() = 0;
};

// The mock
class MockMyInterface: public MyInterface{
    public:
        MOCK_METHOD0(GetUniqueTest, TTest());
        MOCK_METHOD0(GetUniqueInt, std::unique_ptr<int>());
        MockMyInterface() {
            ON_CALL(*this, GetUniqueTest())
                .WillByDefault(Return(ByMove(TTest(0))));
        }
};
//我的模拟接口
类MyInterface
{
公众:
虚拟~MyInterface(){}
虚拟测试GetUniqueTest()=0;
虚拟std::unique_ptr GetUniqueInt()=0;
};
//嘲弄
类MockMyInterface:公共MyInterface{
公众:
MOCK_方法0(GetUniqueTest,TTest());
MOCK_METHOD0(GetUniqueInt,std::unique_ptr());
MockMyInterface(){
调用时(*this,GetUniqueTest())
.WillByDefault(返回(ByMove(TTest(0)));
}
};

参考:[使用仅移动类型的模拟方法]
()

我觉得google test 1.8似乎支持模拟这些功能:更新到google test 1.8可能是个好主意。@我的是的,我后来也发现了,但没有时间验证:)也许当你确认后,你也可以自行回答;)我还没有核实,但我相信这份文件。不管怎样,我的问题指定gtest版本是1.7,它还没有这种支持。是的,我验证了1.8.0版本支持仅移动类型。如果我们希望返回TTest(1)呢。WillByDefault(返回(ByMove(TTest(1)));然后返回1,对吗?
// My interface to mock
class MyInterface
{
    public:
        virtual ~MyInterface() {}
        virtual TTest GetUniqueTest() = 0;
        virtual std::unique_ptr<int> GetUniqueInt() = 0;
};

// The mock
class MockMyInterface: public MyInterface{
    public:
        MOCK_METHOD0(GetUniqueTest, TTest());
        MOCK_METHOD0(GetUniqueInt, std::unique_ptr<int>());
        MockMyInterface() {
            ON_CALL(*this, GetUniqueTest())
                .WillByDefault(Return(ByMove(TTest(0))));
        }
};