python - How to mock calls to function that receives mutable object as parameter? -
consider example:
def func_b(a): print def func_a(): = [-1] in xrange(0, 2): a[0] = func_b(a)
and test function tries test func_a , mocks func_b:
import mock mock import call def test_a(): datatransform.test import func_a mock.patch('datatransform.test.func_b', autospec=true) func_b_mock: func_a() func_b_mock.assert_has_calls([call(0), call(1)])
after func_a has executed try test if func_a made correct calls func_b, since in loop mutating list in end get:
assertionerror: calls not found. expected: [call(0), call(1)] actual: [call([1]), call([1])]
the following works (the importing mock
unittest
python 3 thing, , module
func_a
, func_b
are):
import mock 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))
this inherits magicmock
, , redefines call behaviour deepcopy arguments , keyword arguments.
def test_a(): module import func_a mock.patch('module.func_b', new_callable=modifiedmagicmock) func_b_mock: func_a() func_b_mock.assert_has_calls([call([0]), call([1])])
you can pass new class patch
using new_callable
parameter, cannot co-exist autospec
. note function calls func_b
list, call(0), call(1)
has changed call([0]), call([1])
. when run calling test_a
, nothing (passes).
now cannot use both new_callable
, autospec
because new_callable
generic factory in our case magicmock
override. autospeccing cool mock
's feature, don't want lose it.
what need replace magicmock
modifiedmagicmock
our test: want avoid change magicmock
behavior tests... dangerous. have tool , patch
, used new
argument replace destination.
in case use decorators avoid indentation , make more readable:
@mock.patch('module.func_b', autospec=true) @mock.patch("mock.magicmock", new=modifiedmagicmock) def test_a(func_b_mock): module import func_a func_a() func_b_mock.assert_has_calls([call([0]), call([1])])
or:
@mock.patch("mock.magicmock", new=modifiedmagicmock) def test_a(): mock.patch('module.func_b') func_b_mock: module import func_a func_a() func_b_mock.assert_has_calls([call([0]), call([1])])
Comments
Post a Comment