如何测试从外部基类派生的类,这取决于外部系统

时间:2016-05-04 17:21:37

标签: c++ unit-testing mocking googletest

我有一个类是外部类的子类,我没有任何控件。外部类依赖于系统资源。例如

class MyClass : public ExternalBase // This class is from external framework and framework requires it to derive from this class.
{
    int doSomePrivateThing(int );
public: 

    virtual int DoSomething(int );
    virtual ~MyClass();
}

int MyClass::doSomePrivateThing(int )
{
    // do some private task
}

int MyClass::DoSomething(int n)
{
    // Do MyClass Specific task
    int k = doSomePrivateThing(n);
    return ExternalBase::DoSomething(k); // This function depends on external system resources.
                                         // Probably try to communicate with remote server 
                                         // or attempt access Storage or Display device etc.
}

MyClass::~MyClass()
{}

如何打破MyClass的依赖关系并为MyClass :: DoSomething()编写单元测试。使用组合代替继承不是一种选择,因为框架需要从这个基类派生类。

我正在使用C ++和GoogleTest / Mock。但是,任何普遍的解决方案都值得赞赏。

提前致谢。

1 个答案:

答案 0 :(得分:2)

有两种方法。我称之为“更正确”的方式和“非常丑陋”的方式。

“更正确”的方式:

使用一些额外的层来封装外部类函数,而不是部分模拟。

class MyClass : public ExternalBase // This class is from external framework and framework requires it to derive from this class.
{
    int doSomePrivateThing(int );
public: 
    virtual void BaseDoSomething(int) { return ExternalBase::DoSomething(v); }
    virtual int DoSomething(int v);
    virtual ~MyClass();
};

int MyClass::DoSomething(int n)
{
    // Do MyClass Specific task
    int k = doSomePrivateThing(n);
    return BaseDoSomething(k); 
}

以这种方式在UT中进行局部模拟:

class TestableMyClass : public MyClass
{
public:
    using MyClass::MyClass;
    MOCK_METHOD1(BaseDoSomething, int(int));
}; 

TEST(A,A)
{
    TestableMyClass objectUnderTest;
    EXPECT_CALL(objectUnderTest, BaseDoSomething(112));

    objectUnderTest.DoSomething(112);
}

当你需要在测试中调用真正的基类方法时 - 使用带有EXPECT_CALL的WillOnce(Invoke...)

“非常丑陋”的方式:

提供您自己的UnitBest ExternalBase实现并将其链接到您的测试。 ExternalBase的这个“UnitTest”实现应该基于一些全局的Mocks对象。

<强> ExternalBaseMock.hpp:

class ExternalBaseMock 
{
public:
    MOCK_METHOD1(DoSomething, int(int));
};
extern ExternalBaseMock  externalBaseMock;

<强> ExternalBaseMock.cpp:

ExternalBaseMock  externalBaseMock;

int ExternalBase::DoSomething(int n)
{
    return externalBaseMock.DoSomething(n);
}

然后你的测试:

#include "ExternalBaseMock.hpp"

TEST(A,A)
{
    MyClass objectUnderTest;
    EXPECT_CALL(externalBaseMock, DoSomething(112));

    objectUnderTest.DoSomething(112);
}