我正在尝试从 GMocked 类返回一个 rapidjson::值,但我似乎无法让它工作

I'm trying to return a rapidjson::Value from a GMocked class but I can't seem to get it to work

本文关键字:工作 rapidjson GMocked 返回 一个      更新时间:2023-10-16

我试图对我的一个类进行单元测试,但很难从我的模拟类中返回一个rapidjson::值。

我浏览过互联网,但到目前为止还没有成功。这是我最后的尝试。

我正在运行的代码如下;

class json_action_audit_generator_tests : public ::testing::Test 
{
std::string test_focus_array = "[[11,12],[21,22],[31,32],[41,42],[51,52],[61,62],[71,72],[81,82],[91,92],[101,102],[111,112],[121,122],[131,132]]";
Value create_json_key_from_enum(storage_enum mapped_value, rapidjson::Document& root)
{
return Value(storage_from_enum[mapped_value].c_str(), root.GetAllocator());
}
}
TEST_F(json_action_audit_generator_tests, TestAddJsonFocusInformation)
{
std::stringstream ss;
ss << "{"" << storage_from_enum[storage_enum::JsonFocus] << "":"
<< "["
<< "[" << "11,12" << "]" << ","
<< "[" << "21,22" << "]" << ","
<< "[" << "31,32" << "]" << ","
<< "[" << "41,42" << "]" << ","
<< "[" << "51,52" << "]" << ","
<< "[" << "61,62" << "]" << ","
<< "[" << "71,72" << "]" << ","
<< "[" << "81,82" << "]" << ","
<< "[" << "91,92" << "]" << ","
<< "[" << "101,102" << "]" << ","
<< "[" << "111,112" << "]" << ","
<< "[" << "121,122" << "]" << ","
<< "[" << "131,132" << "]"
<< "]"
<< "}";
rapidjson::Document root;
root.SetObject();
Value json_focus_information(rapidjson::kObjectType);
add_json_string_member(root, root, create_json_key_from_enum(storage_enum::JsonFocus, root), test_focus_array.c_str());

json_action_audit_generator testee(dashboard_action.get(), EKS.get(), json_focus_serializer.get());
----------
EXPECT_CALL(*json_focus_serializer, get_focus_as_json_value()).WillOnce(Return(&json_focus_information));
----------
testee.add_json_focus_information();
EXPECT_EQ(ss.str(), testee.create_json_string());
};

我希望返回一个有效的rapidjson::值,但它目前没有编译并返回以下错误

C2248 - 'rapidjson::GenericValue<rapidjson::UTF8<char>,rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>>::GenericValue':
cannot access private member declared in class 
'rapidjson::GenericValue<rapidjson::UTF8<char>,rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>>'

这让我想到了以下gmock操作。h

template <typename R>
class ReturnAction {
public:
// Constructs a ReturnAction object from the value to be returned.
// 'value' is passed by value instead of by const reference in order
// to allow Return("string literal") to compile.
explicit ReturnAction(R value) : value_(new R(std::move(value))) {}
// This template type conversion operator allows Return(x) to be
// used in ANY function that returns x's type.
template <typename F>
operator Action<F>() const {  // NOLINT
// Assert statement belongs here because this is the best place to verify
// conditions on F. It produces the clearest error messages
// in most compilers.
// Impl really belongs in this scope as a local class but can't
// because MSVC produces duplicate symbols in different translation units
// in this case. Until MS fixes that bug we put Impl into the class scope
// and put the typedef both here (for use in assert statement) and
// in the Impl class. But both definitions must be the same.
typedef typename Function<F>::Result Result;
GTEST_COMPILE_ASSERT_(
!std::is_reference<Result>::value,
use_ReturnRef_instead_of_Return_to_return_a_reference);
static_assert(!std::is_void<Result>::value,
"Can't use Return() on an action expected to return `void`.");
return Action<F>(new Impl<R, F>(value_));
}
private:
// Implements the Return(x) action for a particular function type F.
template <typename R_, typename F>
class Impl : public ActionInterface<F> {
public:
typedef typename Function<F>::Result Result;
typedef typename Function<F>::ArgumentTuple ArgumentTuple;
// The implicit cast is necessary when Result has more than one
// single-argument constructor (e.g. Result is std::vector<int>) and R
// has a type conversion operator template.  In that case, value_(value)
// won't compile as the compiler doesn't known which constructor of
// Result to call.  ImplicitCast_ forces the compiler to convert R to
// Result without considering explicit constructors, thus resolving the
// ambiguity. value_ is then initialized using its copy constructor.
explicit Impl(const std::shared_ptr<R>& value)
: value_before_cast_(*value),
value_(ImplicitCast_<Result>(value_before_cast_)) {}

----------
Result Perform(const ArgumentTuple&) override { return value_; }
----------
private:
GTEST_COMPILE_ASSERT_(!std::is_reference<Result>::value,
Result_cannot_be_a_reference_type);
// We save the value before casting just in case it is being cast to a
// wrapper type.
R value_before_cast_;
Result value_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(Impl);
};

任何帮助都将不胜感激!很抱歉缺少语法突出显示。。。我不知道怎么回事。如果有人给我指明了正确的方向,我会很高兴地更新这个问题。

更新#1

模拟类使用的当前接口

#pragma once
#include "document.h"
#include <string>
class json_focus_serializer_interface {
public:
json_focus_serializer_interface() = default;
virtual ~json_focus_serializer_interface() = default;
virtual rapidjson::Value get_focus_as_json_value() = 0;
virtual std::string get_focus_as_json_string() = 0;
};

当前模拟类定义

#pragma once
#include "json_focus_serializer_interface.h"
#include "gmock/gmock.h"

class mock_json_focus_serializer_interface : public json_focus_serializer_interface {
public:
mock_json_focus_serializer_interface() = default;
~mock_json_focus_serializer_interface() = default;
MOCK_METHOD(rapidjson::Value, get_focus_as_json_value, (), (override));
MOCK_METHOD(std::string, get_focus_as_json_string, (), (override));
};

问题是在EXPECT_CALL中,您试图从声明为返回rapidjson::Value的函数返回rapidjson::Value*

如果rapidjson::Value有一个合适的复制构造函数,那么您所需要做的就是使用WillOnce(Return(json_focus_information))(注意缺少的"与"符号(。

然而,由于rapidjson不允许在不指定分配器的情况下创建rapidjson::Value的副本,所以事情就不那么容易了。我知道的从mock返回json_focus_information副本的一种方法是使用::testing::Invoke操作,而不是像下面这样的::testing::Return

auto return_json_focus_information = [&]() -> rapidjson::Value {
static auto allocator = rapidjson::MemoryPoolAllocator{};
return rapidjson::Value{json_focus_information, allocator};
}
EXPECT_CALL(*json_focus_serializer, get_focus_as_json_value())
.WillOnce(::testing::Invoke(return_json_focus_information));

但请注意,与testing::Return不同,副本将在调用get_focus_as_json_value时创建,而不是在设置期望时创建。

然而,如果在测试的其他地方甚至不需要json_focus_information变量,那么也可以使用

auto return_json_focus_information = []() -> rapidjson::Value {
return rapidjson::Value{rapidjson::kObjectType};
}
EXPECT_CALL(*json_focus_serializer, get_focus_as_json_value())
.WillOnce(::testing::Invoke(return_json_focus_information));

并完全去掉原来的CCD_ 13变量。