GoogleTest / Mock SaveArg быстрой json :: Значение & - PullRequest
1 голос
/ 28 апреля 2020

Я пытаюсь использовать GoogleTest для возврата аргумента, переданного функции. Объявление этой функции выглядит так:

void foo(rapidjson::Value &element, int number) {}

Я бы создал ON_CALL вот так

rapidjson::Value elementVal;
ON_CALL(SomeClassNameWhereFooIsAMember, foo).WillByDefault(SaveArg<0>(&elementVal));

Я не могу даже скомпилировать это.

error 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>>'

Есть идеи?

Обновление1:

Я попробовал следующее в соответствии с ответом Криса Олсена

#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "rapidjson/document.h"

using namespace ::testing;

class FooClass
{
public:
    virtual void foo(rapidjson::Value& element, int number) {}
};

class MockFoo : public FooClass
{
public:
    MOCK_METHOD(void, foo, (rapidjson::Value& element, int number));
};

ACTION_P(SaveRapidJsonValueArg, p)
{
    rapidjson::Document d;  // Needed only to get the required allocator param
    p->CopyFrom(arg0, d.GetAllocator());
}

TEST(RapidJsonTests, SaveArgTest)
{
    MockFoo mock;

    rapidjson::Document document;
    rapidjson::Document::AllocatorType& allocator = document.GetAllocator();

    rapidjson::Value object(rapidjson::kObjectType);
    object.AddMember("Math", "50", allocator);
    object.AddMember("Science", "70", allocator);
    object.AddMember("English", "50", allocator);
    object.AddMember("Social Science", "70", allocator);

    rapidjson::Value saveVal;

    ON_CALL(mock, foo).WillByDefault(SaveRapidJsonValueArg(&saveVal));

    mock.foo(object, 1);

    if (saveVal.HasMember("Math"))
        std::cout << saveVal["Math"].GetString() << "\n";
}

Сбой выполнения при вызове HasMember().

Update2:

Еще раз спасибо Крис Олсен! Вот что я в итоге сделал.

ACTION_P2(SaveRapidJsonValueArg, valuePtr, doc)
{
    valuePtr->CopyFrom(arg1, doc->GetAllocator());
}

TEST(RapidJsonTests, SaveArgTest)
{
    ...
    ...

    ON_CALL(mock, foo).WillByDefault(SaveRapidJsonValueArg(&saveVal, &document));

    ...
    ...
}

Еще раз спасибо, Крис!

1 Ответ

0 голосов
/ 01 мая 2020

Трудно сказать, где проблема, из показанного кода. Вы должны попытаться предоставить минимальный воспроизводимый пример , когда это возможно.

Одна из проблем, с которой вы можете столкнуться, заключается в том, что Rapid JSON не позволяет нормально копировать Value объекты. Вместо этого он использует семантику перемещения. Из учебника Rapid JSON :

Особое решение при разработке Rapid JSON состоит в том, что присвоение значения не копирует исходное значение в целевое значение. Вместо этого значение из источника перемещается в место назначения. Например,

Value a(123);
Value b(456);
b = a;         // a becomes a Null value, b becomes number 123.

Чтобы фактически сделать копию объекта Value, вы можете использовать метод Value::CopyFrom. Для этого в gMock можно использовать пользовательское действие :

#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "rapidjson/document.h"

using namespace ::testing;

class FooClass
{
public:
    virtual void foo(rapidjson::Value& element, int number) {}
};

class MockFoo : public FooClass
{
public:
    MOCK_METHOD(void, foo, (rapidjson::Value& element, int number));
};

struct CaptureFooValue
{
    void operator()(const rapidjson::Value &element, int) const
    {
        v.CopyFrom(element, d.GetAllocator(), true);
    }
    rapidjson::Value &v;
    rapidjson::Document &d;
};

TEST(RapidJsonTests, SaveArgTest)
{
    MockFoo mock;
    rapidjson::Document document;
    rapidjson::Document::AllocatorType& allocator = document.GetAllocator();

    rapidjson::Value object(rapidjson::kObjectType);
    object.AddMember("Math", "50", allocator);
    object.AddMember("Science", "70", allocator);
    object.AddMember("English", "50", allocator);
    object.AddMember("Social Science", "70", allocator);

    rapidjson::Value saveVal;

    ON_CALL(mock, foo).WillByDefault(CaptureFooValue{saveVal, document});

    mock.foo(object, 1);

    if (saveVal.HasMember("Math"))
        std::cout << saveVal["Math"].GetString() << "\n";
}
...