假设我决定用 C 或任何其他过程编程语言编写一个大型应用程序。它具有如下所示的调用依赖函数:
A
|
+-------------+
| |
B1 B2
| |
+------+ +------+
| | | |
C11 C12 C21 C22
显然,对叶子函数 C11、C12、C21 和 C22 进行单元测试非常容易:设置输入、调用函数、断言输出。
但是,为 B1、B2 和 A 启用良好的单元测试的正确策略是什么?
会Dependency Injection建议
B1
(和 B2
也)声明如下?// Declare B1 with dependency injection for invoking C11 and C12.
int B1(int input, int (*c11)(int), int(*c12)(int));
但是,如果我有多层调用,该策略似乎无法扩展。想象一下
A
的声明是什么看起来像:int A(int input, int (*b1)(int, int (*)(int), int(*)(int)),
int(*b2)(int, int (*)(int), int(*)(int)),
int (*c11)(int),
int (*c12)(int),
int (*c21)(int),
int (*c22)(int));
呸!一定有更好的方法。
有时,我觉得 DI 和其他旨在促进模块化和易于维护的类似模式实际上阻碍了代码的清晰度,并使应该直接编码的内容变得复杂,变成了无意义的抽象和复杂的间接。
C 语言的大型软件项目,如 Perl 和 Ruby,如何处理单元测试?
最佳答案
如果您只需要 DI 进行单元测试,您可以使用链接器来完成它。
我的意思是函数 B1 和 B2 在头文件中声明并由函数 A 使用,因此 B 函数的实现由链接器提供。您只需要为单元测试提供不同的 C 文件。这应该不是一个大问题,因为无论如何您可能都有自己的单元测试生成文件。
如果您需要在运行时进行动态依赖解析,您应该为函数指针使用工厂模式(返回函数指针的函数),并在需要时从工厂中提取它们。工厂可以根据全局上下文决定返回什么函数。
关于dependency-injection - 过程编程的依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5527785/