关于依赖注入和单元测试的c++问题

C++ question on dependency injection and unit tests

本文关键字:单元测试 c++ 问题 注入 于依赖 依赖      更新时间:2023-10-16

假设我有一个类BigClass,它需要一个SmallClass类型的成员变量

class BigClass {
.....
private:
SmallClass obj;
};

我有两个问题:

1)我不能将SmallClass对象传递给BigClass的构造函数,因为BigClass需要处理一些文件(并获取一些数据)来正确地实例化SmallClass。我知道做依赖注入的正确方法是有一个构造函数BigClass(SmallClass& obj)。如果SmallClass只能在BigClass实例化之后才实例化,我该如何解决这个问题活了一段时间?

2)这就是BigClass构造自己的方式:它循环遍历目录中的文件,读取一些文件来初始化它的状态。我如何使这个单元可测试?对于从目录中读取文件以获取状态的构造函数来说,什么是合适的单元测试?

1)为了我,你必须为SmallClass引入一个工厂,并让BigClass依赖于它来构建SmallClass实例。

2)在我看来,在构造函数中有这个是一个坏主意,也许有一些显式的方法会有所帮助(但需要更多的正确回复)。

Turn

SmallClass obj;

SmallClass* obj;

然后创建一个方法

setObj(SmallClass* _obj);

这样你就可以在任何你需要的时候实例化它。您还可以注入一个模拟版用于测试。

1)只需在BigClass中创建一个函数,您可以随时将其传递给SmallClass对象。它不一定要在构造函数func(SmallClass* obj)

2)我会通过让你的程序生成一堆文件并将它们放入一个目录来对你的读取文件的BigClass进行单元测试。然后在这些文件上运行bigClass,并根据bigClass应该给出的已知输出,以及您想要测试的任何其他功能,测试每个读取。

您可以对SmallClass进行两阶段初始化,即有一个构造函数使其进入稳定但空的状态,然后有一个init()函数将SmallClass的空壳变成一个工作和可用的对象。

这不是最优雅的解决方案(我个人不喜欢两阶段初始化,因为你可以有浮动的对象,不是真正可用的),但它会在你的场景工作。

另一种选择可能是在BigClass中使用SmallClass *,并使用一个工厂来创建SmallClass对象,并使用它来控制依赖注入。

1)创建一个工厂,对于单元测试,将创建对象的方法更改为创建一个mock。

2)你可以创建另一个类,它有一个接口和派生,这是一个包装器调用获取文件列表。然后,对于单元测试,传递一个模拟对象。您可以将这个类的对象传递给BigClass的构造函数,或者使用工厂。

for 1),它是这样的(未测试):

struct Factory
{
  static SmallClassIface* Create()
  {
    return ReallyCreate();
  }
  typedef SmallClassIface* (funcPtr*)();
  static funcPtr creator;
  static SmallClassIface* DefaultCreator()
  {
    return new SmallClass;
  }
};
Factory::funcPtr Factory::creator = &Factory::DefaultCreator();

BigClass需要处理一些文件…正确实例化SmallClass

我建议不要让构造函数执行I/O。考虑重新设计BigClass,使I/O在调用BigClass构造函数之前完成,并将该I/O的结果传递给BigClass构造函数。

我知道做依赖注入的正确方法

我断言(尽管有些人不同意我的观点),不应该对仅作为实现细节存在的对象进行依赖注入。在这种情况下,如果BigClass没有返回SmallClass对象副本或引用的getter方法,那么BigClassSmallClass的存在是一个实现细节,应该与单元测试无关。