gpt4 book ai didi

c++ - 有没有办法打破这种对单元测试的依赖?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:20:53 25 4
gpt4 key购买 nike

我的 A 类依赖于 B 类。这是代码

//declaration
class A
{
public:
A(B *b);
~A();
void m1();
private:
B *ptr_b;
};

//implementation
A::A(B *b)
{
ptr_b = b;
}

A::~A()
{
delete ptr_b;
}

void A::m1()
{
ptr_b->m2();
}

我想用以下解决方案打破这种依赖性(用于单元测试)。这是代码

 class FakeB : public B 
{
public:
FakeB();
~FakeB();
virtual void m2() = 0;
};

class StubB : public FakeB
{
public:
StubB();
~StubB();
void m2();
}

但是当我实例化类 A 并使用以下代码调用其方法 m1() 时

A *ptr_a = new A(new StubB);
ptr_a->m1();

方法 m1() 调用 B 的方法 m2() 因为 B 的 m2() 不是虚拟的。B类是来自另一个模块的遗留代码我不想更改它的代码但我也不想更改 A 类的代码。

有什么解决方案可以打破这种依赖关系吗?

最佳答案

首先,在类 A 的析构函数中有一个 delete ptr_b; 是糟糕的设计,因为在 A 类的构造函数中没有 new B()。这意味着每次创建 A 的实例时,您都会将 B 对象的所有权转移给 A,从而使您面临对使用 A 而不知道内部结构的人进行重复删除 的潜在风险。

其次,如果您想给 A 一个“ stub ”(或“模拟”或“伪造”)对象而不是“真正的 B”,BFakeB 需要一个公共(public)接口(interface),其中包含 A 需要的所有 B 方法作为虚拟方法:

class FakeB : public InterfaceB 

class B : public InterfaceB 

所以A的所有成员函数都可以使用类型为InterfaceB *的参数,而不是B *。然后将 FakeB 对象注入(inject) A 显然很容易。

不幸的是,这意味着您必须更改 B(至少,一点点)。如果那不是一个选项,总是有可能用某个类 WrapperB 包装 B(这与经典 Adapter pattern 中的想法基本相同):

class WrapperB: public InterfaceB 
{
B _b;
public:
WrapperB(/* some parameters */) : _b(/* same parameters */){}

// Here you need to implement all methods of
// InterfaceB and delegate them to the original method calls
// of _b. You should give them the same name and signature as
// the corresponding (non-virtual) methods in B.
// For example, if there is a method m2 in B,
// there should be a pure virtual method m2 in InterfaceB, and
// an implementation here like this:
virtual void m2(){ _b.m2(); }
};

WrapperB 将只包含非常简单、直接的方法委托(delegate)代码,您可以省略单元测试。当你要将它与 A 结合使用时,你必须使用 WrapperB 而不是 B。但是你得到的是一个完全可单元测试的 class A.

另一种(也许更好)变体是以一种从外部向其中注入(inject)对 B 对象的引用的方式构造 WrapperB 类:

class WrapperB: public InterfaceB 
{
B& _b;
public:
WrapperB(B& b) :_b(b){}

// implement InterfaceB methods as above
virtual void m2(){ _b.m2(); }

}

你可以像这样使用它:

B b;
A a(WrapperB(b));

FakeB fb;
A a_for_test(fb);

关于c++ - 有没有办法打破这种对单元测试的依赖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5242465/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com