为什么我需要像调用方法一样调用我的模拟对象?
我看了很多关于Python 3和模拟(mocking)的资料,但还是搞不清楚为什么我需要在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中的模拟。
1 个回答
2
首先,我们来给这个变量换个名字,因为它其实是一个模拟的 run.Client
实例:
@patch('run.Client')
def test(self, mock_client):
# ...
mock_client().service.GetWeather.assert_called_once_with(weather_id)
你在 run
里面创建了一个 Client
的实例,并且在你的代码中使用了它。但在这个测试中,你并没有真正模拟这个实例,而是模拟了这个类(run.Client
被修改了)。
所以我们有一个模拟的类,而你是通过这个类来创建一个实例。这个实例就是你的代码实际使用的。这意味着你真正想要的是访问这个类构造函数的返回值:
mock_client.return_value.service.GetWeather.assert_called_once_with(weather_id)
这和你的代码是一样的,只是没有调用 mock_client()
。你当前的测试代码做的事情类似:调用模拟的类,看看你得到什么实例,然后对这个实例进行验证。然而,mock
库已经提供了 return_value
属性来实现这一点。