How can we write gtest for a method which calls a method of protected defined class member?

48 Views Asked by At
// Memory.h

#include "Block.h"

namespace User{

class Memory
{
    
protected:
    Block block_instance;
    
public:
    BlockList* GetBlockList();
    
};

}
// Memory.cpp

#include "Memory.h"

namespace User{
const BlockList* Memory::GetBlockList()
{
    return block_instance.GetList();
}
}

I want to test GetBlockList from Memory class with gtest, but I suppose I need to use gmock to mocking Block Class. block_instance is protected variable and I suppose use EXPECT_CALL for its return value. How can we mock this scenario, how can we write test for it ?

I tried to define interface but I can't access to block_instance. I had build errors. I can not imagine how can I access to block_instance and test the return value of it in other method.

1

There are 1 best solutions below

0
Pepijn Kramer On

I would expect something along these lines (with dependency injection)

// make abstract baseclasses for classes involved in unit tests
class BlockListItf
{
};

class BlockItf
{
public:
    virtual BlockListItf& GetList() = 0;
};

class Block :
    public BlockItf
{
    BlockListItf& GetList() override 
    {
        return m_list; // or something like this.
    }
};

// for your unit tests you can make mocks
// these can help you determine what Memory will be
// doing to a Block when it is being tested.
class BlockMock
{
public:
    MOCK_METHOD(BlockListItf&,GetList, (), (override));
};

// The memory class should no longer create a block itself
// but it must be injected (standard design for unit testability)
class Memory
{
public:
    // dependency injection
    // allows for runtime selection of a block implementation
    // either production code of a mock
    explicit Memory(BlockItf& block) : m_block{block} 
    {
    };


    // I prefer returning & when something cannot by design
    // be a nullptr. Again return an abstract baseclass
    // not an actual implementation
    const BlockListItf& Memory::GetBlockList()
    {
        return m_block_itf.GetList();
    }

protected:
    BlockItf& m_block_itf;
    
private:
    BlockListItf& m_blocklist;
};

// And then in unit testing use dependency injection

TEST_F(SomeUnitTest,construct)
{
    BlockMock block_mock;
    
    // todo write a function that will return a block list mock
    ON_CALL(factory, DoMakeTurtle).WillByDefault(Return(MakeBlockListMock())); 

    // setup call expectation
    EXPECT_CALL(block_mock, GetBlockList).Times(1);

    Memory memory(block_mock);
    auto& block_list = memory.GetBlockList();
    ASSERT(block_list.size() > 0 ); // or some other test you can think of

}