假设我有一个类BigClass需要一个SmallClass类型的成员变量
class BigClass {
.....
private:
SmallClass obj;
};
我有两个问题:
1)我无法将SmallClass对象传递给BigClass的构造函数,因为BigClass需要处理一些文件(并获取一些数据)才能正确实例化SmallClass。我知道
进行依赖注入的正确方法是使用构造函数BigClass(SmallClass& obj)
。如果SmallClass只能在BigClass之后实例化,我该如何解决这个问题呢?
住了一段时间?
2)这就是BigClass构建自身的方式:它遍历目录中的文件,读取一些文件以初始化其状态。如何使这个单元可测试?什么是从目录中读取文件以获取状态的构造函数的适当单元测试?
答案 0 :(得分:1)
1)为了我,你必须为SmallClass引入一个工厂,并根据它为BigClass实例构建BigClass。
2)在我看来,在构造函数中使用它是一个坏主意,也许有一些显式方法会有所帮助(但需要更多才能正确回复)。
答案 1 :(得分:0)
打开
SmallClass obj;
到
SmallClass* obj;
然后,制作一个方法
setObj(SmallClass* _obj);
这样你就可以随时实例化它。您还可以注入一个模拟版本进行测试。
答案 2 :(得分:0)
1)只需在BigClass中创建一个函数,您可以随时传入SmallClass对象。它不必位于构造函数func(SmallClass* obj)
2)我会通过让你的程序生成一堆文件并将它们放入一个目录来对你的BigClass进行单元测试。然后在这些文件上运行bigClass,并根据BigClas提供的已知输出测试单个读取,以及您要测试的任何其他功能。完成后删除文件。
答案 3 :(得分:0)
您可以在SmallClass
上进行两阶段初始化,即使用一个构造函数将其置于一个稳定但空的状态,然后使用init()
函数转换SmallClass
的空壳。 1}}成为一个工作和可用的对象。
这不是最优雅的解决方案(我个人不喜欢两阶段的初始化,因为你可以让周围的物体无法真正使用),但它可以在你的场景中使用。
另一种选择可能是在SmallClass *
中使用BigClass
并使用创建SmallClass
对象的工厂并使用它来控制依赖注入。
答案 4 :(得分:0)
1)创建工厂,对于单元测试,更改创建对象的方法以创建模拟。
2)你可以创建另一个具有接口和派生的类,它是调用获取文件列表的包装器。然后,对于单元测试,您传递一个模拟对象。您可以将此类的对象传递给BigClass的构造函数,也可以使用工厂。
表示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();
答案 5 :(得分:0)
BigClass
需要处理一些文件......以正确实例化SmallClass
我建议不要让构造函数执行I / O.考虑重新设计BigClass
,以便在调用BigClass
构造函数之外(之前)完成I / O,并将该I / O的结果传递给BigClass
构造函数。
我知道进行依赖注入的正确方法
我断言(虽然有些人不同意我的观点),你不应该对仅作为实现细节出现的对象进行依赖注入。在这种情况下,如果BigClass
没有getter方法返回SmallClass
对象的副本或引用,则SmallClass
中BigClass
的存在是一个实现细节,应与您的单元测试无关。