我已经阅读了有关Python 3和模拟的所有内容。不幸的是,当我读过的所有文档都使用后者时,我仍然无法弄清楚为什么我需要在mock()
而不是mock
验证断言。
这是我测试的样子 -
from unittest.mock import Mock, patch
from unittest import TestCase, skip
from suds.client import Client, ServiceDefinition
from run import WebService
import unittest
@patch('run.Client')
def test(self, mock):
service = WebService()
weather_id = 1234
weather = service.get_weather(weather_id)
mock().service.GetWeather.assert_called_once_with(weather_id)
在这种情况下, run
是WebService
所在的位置,Client
是suds
客户。
打印mock.mock_calls
我看到了 -
[
call('SERVICE_WSDL', proxy={'https': 'PROXY', 'http': 'PROXY'}),
call().factory.create('AuthHeader'),
call().set_options(soapheaders=<MagicMock name='Client().factory.create()' id='37553264'>),
call().service.GetWeather(1234, '', '')
]
请注意,我的测试通过。我只是想知道我错过了什么,所以我可以更好地理解Python中的嘲笑。
答案 0 :(得分:2)
首先,让我们重命名该变量,因为它实际上是run.Client
的模拟实例:
@patch('run.Client')
def test(self, mock_client):
# ...
mock_client().service.GetWeather.assert_called_once_with(weather_id)
您正在Client
内创建run
的实例,并且您已在代码中使用该实例。但是你实际上并没有在这个测试中嘲笑那个实例,而是在嘲笑这个类(run.Client
正在修补)。
所以我们有一个模拟类,我们正在调用该类来创建一个实例。该实例是您的代码实际使用的实例。这意味着你真正想要的是访问类的构造函数的返回值:
mock_client.return_value.service.GetWeather.assert_called_once_with(weather_id)
除了不调用mock_client()
之外,这与您的代码相同。您当前的测试代码执行类似的操作:调用模拟类,查看您获取的实例并对其执行断言。然而,mock
库提供了return_value
属性来执行此操作。