C++ 伪造的google模拟委托必须是可复制的
使用GoogleTest和mocks,如果函数返回对数据对象的引用,我似乎无法将来自mock的调用委托给fake。我使用的谷歌测试版本是1.10.0版本,来自发布的zip 在下面的代码中,当我从一个模拟委托给一个伪代理时,我会得到一个错误,指示复制ctor被删除。是,必须删除此代码才能正常工作 对于返回类引用的函数,是否有任何方法可以使用gmock将模拟委托给伪函数 请注意,在下面的代码中,有一个宏:C++ 伪造的google模拟委托必须是可复制的,c++,googletest,googlemock,C++,Googletest,Googlemock,使用GoogleTest和mocks,如果函数返回对数据对象的引用,我似乎无法将来自mock的调用委托给fake。我使用的谷歌测试版本是1.10.0版本,来自发布的zip 在下面的代码中,当我从一个模拟委托给一个伪代理时,我会得到一个错误,指示复制ctor被删除。是,必须删除此代码才能正常工作 对于返回类引用的函数,是否有任何方法可以使用gmock将模拟委托给伪函数 请注意,在下面的代码中,有一个宏: #定义使用模拟访问器1 这用于测试所需的测试代码执行路径。 将该值定义为零只会测试Access
#定义使用模拟访问器1
这用于测试所需的测试代码执行路径。
将该值定义为零只会测试AccessorImpl类的行为是否正确。我这样做是为了检查我没有在这个类中对类和实例进行错误格式化。
谢谢你的意见
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include <cstdint>
using ::testing::Invoke;
using ::testing::Mock;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::_;
class Accessor
{
public:
virtual ~Accessor() = default;
Accessor() = default;
Accessor(Accessor const&) = delete;
Accessor(Accessor&&) = delete;
Accessor& operator=(Accessor const&) = delete;
Accessor& operator=(Accessor&&) = delete;
struct Foo
{
~Foo() = default;
Foo() = default;
Foo(Foo const&) = delete;
Foo(Foo&&) = delete;
Foo& operator=(Foo const&) = delete;
Foo& operator=(Foo&&) = delete;
uint32_t thing_1 = 13u;
};
struct Bar
{
~Bar() = default;
Bar() = default;
Bar(Bar const&) = delete;
Bar(Bar&&) = delete;
Bar& operator=(Bar const&) = delete;
Bar& operator=(Bar&&) = delete;
uint32_t thing_2 = 79u;
};
virtual Foo& GetFoo() = 0;
virtual Bar const& GetBar() const = 0;
};
class AccessorImpl: public Accessor
{
public:
~AccessorImpl() override = default;
AccessorImpl() = default;
AccessorImpl(AccessorImpl const& ) = delete;
AccessorImpl(AccessorImpl&&) = delete;
AccessorImpl& operator=(AccessorImpl const&) = delete;
AccessorImpl& operator=(AccessorImpl&&) = delete;
Foo& GetFoo() override { return this->foo_; };
Bar const& GetBar() const override { return this->bar_; };
private:
Foo foo_;
Bar bar_;
};
#define USE_MOCK_ACCESSOR 1
#if USE_MOCK_ACCESSOR
class MockAccessor : public Accessor
{
public:
MOCK_METHOD0(GetFoo, Foo&());
MOCK_CONST_METHOD0(GetBar, Bar&());
};
class MockAccessorWithFake : public MockAccessor
{
public:
MockAccessorWithFake() : MockAccessor(), fake_accessor_()
{
ON_CALL(*this, GetFoo).WillByDefault([this]() {
return this->fake_accessor_.GetFoo();
});
ON_CALL(*this, GetBar).WillByDefault([this]() {
return this->fake_accessor_.GetBar();
});
}
private:
AccessorImpl fake_accessor_;
};
#endif
TEST(AccessorTest, test)
{
#if USE_MOCK_ACCESSOR
MockAccessorWithFake accessor;
#else
AccessorImpl accessor;
#endif
EXPECT_EQ(accessor.GetFoo().thing_1, 13u);
EXPECT_EQ(accessor.GetBar().thing_2, 79u);
}
#包括“gtest/gtest.h”
#包括“gmock/gmock.h”
#包括
使用::testing::Invoke;
使用::testing::Mock;
使用::测试::返回;
使用::testing::ReturnRef;
使用::测试::;
类访问器
{
公众:
virtual~Accessor()=默认值;
Accessor()=默认值;
存取器(存取器常数&)=删除;
访问器(访问器&&)=删除;
访问器和运算符=(访问器常量&)=删除;
访问器和运算符=(访问器和运算符)=删除;
结构Foo
{
~Foo()=默认值;
Foo()=默认值;
Foo(Foo const&)=删除;
Foo(Foo&&)=删除;
Foo&运算符=(Foo const&)=删除;
Foo&运算符=(Foo&&)=删除;
uint32_t thing_1=13u;
};
结构条
{
~Bar()=默认值;
Bar()=默认值;
Bar(Bar const&)=删除;
条形图(条形图&&)=删除;
Bar&运算符=(Bar const&)=删除;
条形图&运算符=(条形图&&)=删除;
uint32_t thing_2=79u;
};
虚拟Foo&GetFoo()=0;
虚拟条常量&GetBar()常量=0;
};
类访问器MPL:公共访问器
{
公众:
~AccessorImpl()override=默认值;
AccessorImpl()=默认值;
AccessorImpl(AccessorImpl const&)=删除;
AccessorImpl(AccessorImpl&&)=删除;
AccessorImpl&运算符=(AccessorImpl const&)=删除;
AccessorImpl&operator=(AccessorImpl&&)=删除;
Foo&GetFoo()重写{返回此->Foo;};
Bar const&GetBar()const override{返回此->Bar;};
私人:
富富!;
酒吧酒吧;
};
#定义使用\u模拟\u访问器1
#如果使用\u MOCK\u访问器
类MockAccessor:公共访问器
{
公众:
模拟方法0(GetFoo,Foo&());
模拟常量方法0(GetBar,Bar&());
};
类MockAccessorWithFake:public MockAccessor
{
公众:
MockAccessor with fake():MockAccessor(),fake_accessor
{
ON_CALL(*this,GetFoo).WillByDefault([this](){
返回此->伪访问器.GetFoo();
});
ON_CALL(*this,GetBar).WillByDefault([this](){
返回此->伪访问器.GetBar();
});
}
私人:
附件mpl伪附件;
};
#恩迪夫
测试(访问测试,测试)
{
#如果使用\u MOCK\u访问器
使用假访问器模拟访问器;
#否则
附加器MPL附加器;
#恩迪夫
EXPECT_EQ(accessor.GetFoo().thing_1,13u);
EXPECT_EQ(accessor.GetBar().thing_279u);
}
来自clang编译器的错误:
test_accessor.cc:83:20: error: call to deleted constructor of 'Accessor::Foo'
return this->fake_accessor_.GetFoo();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test_accessor.cc:26:9: note: 'Foo' has been explicitly marked deleted here
Foo(Foo const&) = delete;
^
test_accessor.cc:82:46: error: no viable conversion from '(lambda at
test_accessor.cc:82:46)' to 'const Action<Accessor::Foo &()>'
ON_CALL(*this, GetFoo).WillByDefault([this]() {
^~~~~~~~~~
googletest-src/googlemock/include/gmock/gmock-actions.h:339:7: note: candidate constructor (the implicit copy constructor) not viable:
no known conversion from '(lambda at test_accessor.cc:82:46)' to 'const testing::Action<Accessor::Foo &()> &' for 1st argument
class Action {
^
googletest-src/googlemock/include/gmock/gmock-actions.h:339:7: note: candidate constructor (the implicit move constructor) not viable:
no known conversion from '(lambda at test_accessor.cc:82:46)' to 'testing::Action<Accessor::Foo &()> &&' for 1st argument
googletest-src/googlemock/include/gmock/gmock-actions.h:367:3: note: candidate template ignored: requirement
'::std::is_constructible<std::__1::function<Accessor::Foo &()>, (lambda at test_accessor.cc:82:46)>::value' was not satisfied
[with G = (lambda at test_accessor.cc:82:46)]
Action(G&& fun) : fun_(::std::forward<G>(fun)) {} // NOLINT
^
googletest-src/googlemock/include/gmock/gmock-spec-builders.h:323:46: note: passing argument to parameter 'action' here
OnCallSpec& WillByDefault(const Action<F>& action) {
test\u accessor.cc:83:20:错误:调用“accessor::Foo”的已删除构造函数
返回此->伪访问器.GetFoo();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test_accessor.cc:26:9:注意:“Foo”已在此处显式标记为deleted
Foo(Foo const&)=删除;
^
test_accessor.cc:82:46:错误:在
测试_accessor.cc:82:46)“到”const Action”
ON_CALL(*this,GetFoo).WillByDefault([this](){
^~~~~~~~~~
googletest src/googlemock/include/gmock/gmock actions.h:339:7:注意:候选构造函数(隐式副本构造函数)不可行:
对于第一个参数,没有已知的从“(test_accessor.cc:82:46处的lambda)”到“const testing::Action&”的转换
集体诉讼{
^
googletest src/googlemock/include/gmock/gmock actions.h:339:7:注意:候选构造函数(隐式移动构造函数)不可行:
对于第一个参数,没有已知的从“(test_accessor.cc:82:46处的lambda)”到“testing::Action&”的转换
googletest src/googlemock/include/gmock/gmock actions.h:367:3:注意:忽略候选模板:需求
“::std::is_constructible::value”未满足要求
[使用G=(测试访问器处的lambda.cc:82:46)]
动作(G&&fun):fun_(::std::forward(fun)){}//NOLINT
^
googletest src/googlemock/include/gmock/gmock spec builders.h:323:46:注意:在此处将参数传递给参数“action”
OnCallSpec和WillByDefault(const操作和操作){
问题1
auto
类型推断条引用的规则。因此,lambda的返回类型被推断为Foo
,而不是Foo&
,后者随后需要一个副本。如果要从lambda返回引用,则必须使用尾部返回类型语法(通过显式设置或将返回类型设置为Foo&
,方法是使用auto&
强制引用类型推断,或使用保留引用的decltype(auto)
。请参阅,在最后一个链接中,相关部分是:“如果P是引用类型,则P引用的类型用于推断。”
因此,您应该更改在调用时传递给的lambda以返回引用类型,例如:
ON_CALL(*this, GetFoo).WillByDefault([this]() -> Foo& {
return this->fake_accessor_.GetFoo();
});
ON_CALL(*this, GetBar).WillByDefault([this]() -> Bar const& {
return this->fake_accessor_.GetBar();
});
如果没有此选项,则会出现以下错误:
test.cpp:83:20: error: call to deleted constructor of 'Accessor::Foo'
return this->fake_accessor_.GetFoo();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:26:9: note: 'Foo' has been explicitly marked deleted here
Foo(Foo const&) = delete;
^
test.cpp:82:46: error: no viable conversion from '(lambda at test.cpp:82:46)' to 'const Action<Accessor::Foo &()>'
ON_CALL(*this, GetFoo).WillByDefault([this]() {
^~~~~~~~~~
如果没有这个变化,下面的er
test.cpp:83:20: error: call to deleted constructor of 'Accessor::Foo'
return this->fake_accessor_.GetFoo();
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.cpp:26:9: note: 'Foo' has been explicitly marked deleted here
Foo(Foo const&) = delete;
^
test.cpp:82:46: error: no viable conversion from '(lambda at test.cpp:82:46)' to 'const Action<Accessor::Foo &()>'
ON_CALL(*this, GetFoo).WillByDefault([this]() {
^~~~~~~~~~
MOCK_CONST_METHOD0(GetBar, Bar const&());
test.cpp:86:46: error: no viable conversion from '(lambda at test.cpp:86:46)' to 'const Action<Accessor::Bar &()>'
ON_CALL(*this, GetBar).WillByDefault([this]() -> Bar const& {
^~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/gmock/gmock-actions.h:357:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from '(lambda at test.cpp:86:46)' to 'const testing::Action<Accessor::Bar &()> &' for 1st argument
class Action {