为什么我需要像方法一样调用我的模拟?

时间:2014-08-20 16:12:08

标签: python python-3.x mocking

我已经阅读了有关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)
在这种情况下,

runWebService所在的位置,Clientsuds客户。

打印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 个答案:

答案 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属性来执行此操作。