c++ - 如何测试从依赖于外部系统的外部基类派生的类

标签 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。但任何通用的解决方案都是值得赞赏的。

提前致谢。

最佳答案

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


“更正确”的方法:

使用一些可以部分模拟的附加层来封装外部类函数。

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);
}

当您还需要在测试中调用真正的基类方法时 - 使用 WillOnce(Invoke...)与 EXPECT_CALL。


“非常丑陋”的方式:

提供您自己的ExternalBase UnitTest 实现并将其链接到您的测试。 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);
}

关于c++ - 如何测试从依赖于外部系统的外部基类派生的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37034220/

相关文章:

unit-testing - 为每个测试重新启动 appdomain

python - 在生产代码中而不是在测试中模拟方法

python - 如何模拟嵌套函数?

c++ - 如何制作抽象模板类的 vector

c++ - 在 C/C++ 中防止缓冲区溢出

c++ - 如何获取对变量值的引用?

python - 仅将关键字参数传递给 __new__() 而永远不会将其进一步传递给 __init__()?

c++ - 如何将函数作为参数传递给transform()函数?

java - 如何在 Maven 构建失败时显示自定义消息

angularjs - 没有模板的测试指令属性