因此示例代码非常基本:
@mock.patch.object(BookForm, 'is_valid')
def test_edit(self, mocked_is_valid):
create_superuser()
self.client.login(username="test", password="test")
book = Book()
book.save()
mocked_is_valid.side_effect = lambda: True
self.client.post(reverse('edit', args=[book.pk]), {})
这很有效。但是在mock中添加autospec关键字:
^{pr2}$导致将其他参数传递给side_effect
可调用项,这显然会导致错误:
TypeError: <lambda>() takes 0 positional arguments but 1 was given
我不明白的是,为什么自动选择会给出额外的论证。我读过docs,但仍然找不到这种行为的解释。在
理论上是这样写的
In addition mocked functions / methods have the same call signature as the original so they raise a TypeError if they are called incorrectly.
所以可以(is_valid
有self
参数,这可能就是这里传递的),但另一方面,它也写了side_effect
的内容
The function is called with the same arguments as the mock, and unless it returns DEFAULT, the return value of this function is used as the return value.
据我所知,即使没有自动选择,也应该使用self
参数调用side_effect
。但事实并非如此。在
is called with the same arguments as the mock
if form.is_valid(): # the mock is_valid is called with the self argument, isn't it?
所以,如果有人能给我解释,最好引用文件,我会很感激的。在
你误解了文件。如果没有
autospec
,则被调用的side_effect
实际上是原样,而不检查原始声明。让我们创建一个更好的最小示例来演示这个问题。在现在,您的原始测试应该可以通过一些调整来工作
^{pr2}$按原样运行测试将导致
Book is valid
被打印到stdout,即使我们还没有完成设置书籍有效标志为true,因为在Client.post
中被调用的self.form.is_valid
被替换为被调用的lambda。我们可以通过调试器看到:同样在
Client.post
方法调用的框架内,它不是一个绑定方法(我们稍后将讨论这个问题)嗯,我们这里可能有个问题:
side_effect
可能是任何与实际情况不同的可调用函数,在我们的例子中,is_valid
函数签名(即参数列表)可能与我们提供的模拟不同。如果BookForm.is_valid
方法被修改为接受一个附加参数,会怎么样:重新运行我们的测试。。。您将看到,我们的测试已经通过了,即使
Client.post
仍然在调用BookForm.is_valid
,而没有任何参数。即使你的测试通过了,你的产品也会在生产中失败。这就是引入autospec
参数的原因,我们将在第二个测试中应用该参数,而不替换callable through side\u效果:现在调用函数时会发生这种情况
这是您想要的,
autospec
打算提供的-调用mock之前的检查,以及因此,我们必须通过提供大于
0
的authcode来修复Client.post
方法。在由于我们的测试没有通过
side_effect
可调用函数来模拟is_valid
函数,因此该方法将以打印Book is invalid
结束。在现在,如果我们想提供
side_effect
,它必须匹配相同的签名Book is valid
现在将再次打印。通过调试器检查autospec
方法调用的框架内的autospec
'并模拟了is_valid
对象啊,不知何故,方法签名不是一个简单的
MagicMock
对象(回想一下前面提到的<MagicMock name='is_valid' id='140554947029032'>
),而是一个正确绑定的方法,这意味着self
参数现在被传递到mock中,解决了这个问题:在本例中,“与mock相同的参数”的含义与传入mock的参数相同。重申一下,第一种情况下,}都将被传递到}的错误行为。在
self.form.is_valid
被替换为一个裸的、无界的可调用的,因此self
永远不会被传递;在第二种情况下,可调用的现在绑定到self
,self
和{side_effect
可调用对象中,就像在实际调用中发生的一样。这应该可以调和与autospec=True
交互的不当行为,以及为模拟调用的手动定义的{相关问题 更多 >
编程相关推荐