Python中的TDD:函数的依赖项注入
我最近参加了一个TDD课程,我一直在努力把学到的东西付诸实践。我一直在编写代码来处理一些json文档,其中涉及到一些进行一些处理的函数,然后调用其他函数来完成部分工作 因此,在一个类中,函数1调用函数2,然后调用函数3,等等。我一直在使用依赖项注入来模拟函数2,这样我就可以断言函数1是如何调用函数2的。这涉及将mock作为参数传递给函数1,当单独开发函数时,函数1可以正常工作。然而,当我想为real运行代码并将所有独立测试的函数串在一起时,我遇到了问题。当我想要传递我的实际函数时,我似乎无法让它工作。下面的代码不起作用,但希望能说明我正在尝试做什么Python中的TDD:函数的依赖项注入,python,unit-testing,dependency-injection,Python,Unit Testing,Dependency Injection,我最近参加了一个TDD课程,我一直在努力把学到的东西付诸实践。我一直在编写代码来处理一些json文档,其中涉及到一些进行一些处理的函数,然后调用其他函数来完成部分工作 因此,在一个类中,函数1调用函数2,然后调用函数3,等等。我一直在使用依赖项注入来模拟函数2,这样我就可以断言函数1是如何调用函数2的。这涉及将mock作为参数传递给函数1,当单独开发函数时,函数1可以正常工作。然而,当我想为real运行代码并将所有独立测试的函数串在一起时,我遇到了问题。当我想要传递我的实际函数时,我似乎无法让它
class myclass:
def function1(self, number, injected_function=function2):
number = number + 1
injected_function(number)
def function2(self, number):
number = number + 2
print(number)
instantiated_class = myclass()
instantiated_class.function1(1)
通常,我会这样做:
class myclass:
def function1(self, number):
number = number + 1
self.function2(number)
def function2(self, number):
number = number + 2
print(number)
instantiated_class = myclass()
instantiated_class.function1(1)
class myclass:
def function1(self, number, injected_function=None):
if injected_function is None:
injected_function = self.function2
number = number + 1
injected_function(number)
def function2(self, number):
number = number + 2
print(number)
但是很明显,这使得测试函数2是如何调用的变得更加困难。我知道在这个场景中可以使用
unittest.mock.patch
,但这真的是所有这些问题的解决方案吗?我感觉我在做一些根本错误的事情——我的TDD方法有错误吗 如果您在问题中添加您遇到的错误,这将非常有用
使用Python3.5运行代码时,它会给我提供name错误:未定义名称“function2”
问题是在function1
定义时间function2
尚未定义。在function1
之前声明它将解决以下问题:
class myclass:
def function2(self, number):
number = number + 2
print(number)
def function1(self, number, injected_function=function2):
number = number + 1
injected_function(number)
这还不能解决所有问题。这里需要技巧的是,您直接引用function2
,而不是通过myclass
,因此在调用injected\u function(number)
时,它不会绑定到类。这意味着参数self
不会自动提供给它,因此function2
将“查看”作为self
传递的参数number
,然后它会抱怨没有收到第二个参数number
您可以通过调用injected\u函数(self,number)
来解决这个问题,但这可能会带来更多麻烦。相反,您可以这样做:
class myclass:
def function1(self, number):
number = number + 1
self.function2(number)
def function2(self, number):
number = number + 2
print(number)
instantiated_class = myclass()
instantiated_class.function1(1)
class myclass:
def function1(self, number, injected_function=None):
if injected_function is None:
injected_function = self.function2
number = number + 1
injected_function(number)
def function2(self, number):
number = number + 2
print(number)
这将起作用,因为您正在使用function2
的引用,该引用将在self
中找到。因此在定义时不需要它,参数self
将绑定到方法调用。同时,提供非方法的函数(不接受self
参数的函数)也不会有问题
你也可以直接使用这个软件包。我为依赖项注入维护这个库。它怎么不工作?是否有任何错误输出?@MrJLP如果您尝试运行第一个块中的代码,您将看到错误类型。我担心我只是使用了错误的设计类型来实现我想要做的事情——在测试过程中可以选择插入模拟函数,否则就使用默认函数