在为我的应用程序编写单元测试时,我一直在使用 @mock.patch
和 @patch.object
装饰器 . 但是现在,对于我使用装饰器的一些单元测试,我收到错误' TypeError: staticmethod object is not an iterator ' .
但是使用相同的代码,如果我使用 mock.patch.object
或 mock.patch.object
,一切正常 .
例如,在我的测试类中,我有这个方法:
@staticmethod
def my_mock():
...do something
当我尝试以下单元测试时
@mock.patch('mypackage.mymodule.my_method', side_effect=my_mock)
def test_something(self, my_method_mocked):
...test something
我收到' TypeError: staticmethod object is not an iterator '之前声明的错误消息 .
但是,当我尝试这种方式
def test_something(self):
with patch.object(mymodule, "my_method") as mocked_method:
mocked_method.side_effect = self.my_mock
...test something
一切都很完美 .
我已经阅读了有关模拟和单元测试的Python文档,但我找不到任何有关此行为的解释 .
使用 decorator pattern 和 with 模式有什么区别?哪里可以找到更多相关信息?
为了更清楚,这是我的代码结构:
class TestClass(unittest.TestCase):
@staticmethod
def my_mock():
...mock
return service
# doesn't work
@mock.patch('mypackage.mymodule.my_method', side_effect=my_mock)
def test_something(self, my_method_mocked):
...test something
# work
def test_something(self):
with patch.object(mymodule, "my_method") as mocked_method:
mocked_method.side_effect = self.my_mock
...test something
那's why I can' t做 TestClass.my_mock
. 如果我这样做,我会收到参考错误 .
2 回答
我想你只需要添加类名
您正在看到Python的描述符协议的影响 . 区别不在于您如何调用
patch
,而是在每种情况下分配给side_effect
属性的值 .如果运行此代码,您将看到类声明中的
print
语句输出<type 'staticmethod'>
,因为您有对方法本身的引用 .另外两个
print
语句输出<type 'function'>
,因为您没有对该方法的引用;你有一个方法的__get__
方法的返回值的引用 . 这两个电话相当于有关如何使用描述符实现三种类型的方法(静态,类和实例)的更全面讨论,请参见https://docs.python.org/2/howto/descriptor.html .
实际的错误是因为
patch
期望一个callable作为side_effect
参数的值,如果失败,它需要一个可迭代的返回值 .staticmethod
对象既不可调用也不可迭代 . (试试吧:A.__dict__['my_mock']()
. )为了确保您获得该功能,您需要通过该类访问该方法 .