单元测试应测试功能并尝试与实现细节无关。
Mock.assert_called_with()
是一个方便的功能,但AFAIK会将*args
与*args
和**kwargs
与**kwargs
进行比较。因此:
# class to be mocked during test
class SomeClass():
def func(self,a,b,c=5):
# ...
# code under test
somaclass_instance.func(1,b=2,c=3)
# test code that works
someclass_mock.func.assert_called_with(1,b=2,c=3)
# test code that won't work
someclass_mock.func.assert_called_with(1,2,c=3)
someclass_mock.func.assert_called_with(a=1,b=2,c=3)
有没有一种方法可以对此进行概括,以便在*args
的调用**kwargs
中使用func
的具体内容(实际上是一个实现细节)将被忽略?
答案 0 :(得分:5)
提交要模拟的功能请求。
基本问题是无法访问实际函数/类模拟无法知道关键字参数的顺序,即调用call(a=1, b=2)
和call(b=2, a=1)
看起来与mock相同,而调用{{1 }和call(1, 2)
没有。
如果你想推广mock,你需要传递一个调用原型或一个函数来代替原型,例如:
call(2, 1)
答案 1 :(得分:1)
从Python 3.4开始,就像你想要的那样,当使用spec创建可调用的Mock时,自动规范化特定的调用签名,并且在使用自动调整时使用对象方法。
从the documentation of the Mock class的最后:
使用spec(或spec_set)创建的可调用模拟将会 在匹配调用时反省规范对象的签名 模拟。因此,它可以匹配实际调用的参数 无论他们是通过职位还是通过名字传递:
>>> def f(a, b, c): pass ... >>> mock = Mock(spec=f) >>> mock(1, 2, c=3) <Mock name='mock()' id='140161580456576'> >>> mock.assert_called_with(1, 2, 3) >>> mock.assert_called_with(a=1, b=2, c=3)
这适用于assert_called_with(),assert_called_once_with(), assert_has_calls()和assert_any_call()。自动指定时,它会 也适用于模拟对象的方法调用。
在3.4版中更改:在已推测和自动指定的模拟对象上添加了签名内省。