python将对象作为函数的参数_python-如何模拟对接收可变对象作为参数的函数的调用?...

考虑示例:

def func_b(a):

print a

def func_a():

a = [-1]

for i in xrange(0, 2):

a[0] = i

func_b(a)

并尝试测试func_a并模拟func_b的测试函数:

import mock

from mock import call

def test_a():

from dataTransform.test import func_a

with mock.patch('dataTransform.test.func_b', autospec=True) as func_b_mock:

func_a()

func_b_mock.assert_has_calls([call(0), call(1)])

执行func_a之后,我尝试测试func_a是否对func_b进行了正确的调用,但是由于在for循环中,我最终对列表进行了变异:

AssertionError: Calls not found.

Expected: [call(0), call(1)]

Actual: [call([1]), call([1])]

解决方法:

以下工作(从unittest导入模拟是Python 3的东西,而模块是func_a和func_b所在的位置):

import mock

from mock import call

import copy

class ModifiedMagicMock(mock.MagicMock):

def _mock_call(_mock_self, *args, **kwargs):

return super(ModifiedMagicMock, _mock_self)._mock_call(*copy.deepcopy(args), **copy.deepcopy(kwargs))

这继承自MagicMock,并重新定义了调用行为以深度复制参数和关键字参数.

def test_a():

from module import func_a

with mock.patch('module.func_b', new_callable=ModifiedMagicMock) as func_b_mock:

func_a()

func_b_mock.assert_has_calls([call([0]), call([1])])

您可以使用new_callable参数将新类传递给patch,但是它不能与autospec共存.请注意,您的函数使用列表调用func_b,因此必须将call(0),call(1)更改为call([0]),call([1]).通过调用test_a运行时,此操作不执行任何操作(通过).

现在我们不能同时使用new_callable和autospec,因为new_callable是通用工厂,但在我们的情况下只是MagicMock替代.但是Autospeccing是非常酷的模拟功能,我们不想失去它.

我们需要的只是为了测试而用ModifiedMagicMock替换MagicMock:我们要避免在所有测试中都更改MagicMock的行为……可能很危险.我们已经有一个工具可以执行此操作,它是补丁程序,与new参数一起用于替换目标位置.

在这种情况下,我们使用装饰器来避免过多的缩进并使之更具可读性:

@mock.patch('module.func_b', autospec=True)

@mock.patch("mock.MagicMock", new=ModifiedMagicMock)

def test_a(func_b_mock):

from module import func_a

func_a()

func_b_mock.assert_has_calls([call([0]), call([1])])

要么:

@mock.patch("mock.MagicMock", new=ModifiedMagicMock)

def test_a():

with mock.patch('module.func_b') as func_b_mock:

from module import func_a

func_a()

func_b_mock.assert_has_calls([call([0]), call([1])])

标签:python,mocking

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值