我有一个类是外部类的子类,我没有任何控件。外部类依赖于系统资源。例如
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。但是,任何普遍的解决方案都值得赞赏。
提前致谢。
答案 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);
}