在Python中模拟__mul__和__rmul__

时间:2016-06-23 11:41:35

标签: python unit-testing mocking

我试图模拟以下代码行:

surface['width'] = '{:~}'.format(self._width * self._scaling_factor_x)

我将_width和_scaling_factor_x作为类unittest.MagicMock的对象传递。之后,我将_width的__mul__方法替换为:

def multiplicateMocks(self, other):
    return MagicMock(name = self.name + '*' + other.name)

但是,此代码不起作用。第二个参数other未通过。 在Python解释器会话中进行测试表明已将__mul__替换为:

def newMul(*args):
    return args

并且调用它,确实只有一个参数存在 - 左手操作数。

可以尝试正确的乘法吗?

更新:充实问题。

a)标准的MagicMock行为:

In [61]: mock1 = MagicMock(name="mock1")
In [62]: mock2 = MagicMock(name="mock2")
In [63]: mock1*mock2
Out[63]: <MagicMock name='mock.__mul__()' id='73472880'>

b)替换“ mul

的预期结果
In [63]: mock1*mock2
Out[63]: <MagicMock name='mock1*mock2' id='73472880'>

c) mul 替换:

def multiplicateMocks(self, other):
    return MagicMock(name = self.name + '*' + other.name)

d)错误的结果:

In [75]: mock1.__mul__.side_effect = multiplicateMocks

In [76]: mock1*mock2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-76-36051f78b408> in <module>()
----> 1 mock1*mock2

c:\users\redacted\appdata\local\programs\python\python35\lib\unittest\mock.py i
n __call__(_mock_self, *args, **kwargs)
    915         # in the signature
    916         _mock_self._mock_check_sig(*args, **kwargs)
--> 917         return _mock_self._mock_call(*args, **kwargs)
    918
    919

c:\users\redacted\appdata\local\programs\python\python35\lib\unittest\mock.py i
n _mock_call(_mock_self, *args, **kwargs)
    981                 return result
    982
--> 983             ret_val = effect(*args, **kwargs)
    984
    985         if (self._mock_wraps is not None and

TypeError: multiplicateMocks() missing 1 required positional argument: 'other'

2 个答案:

答案 0 :(得分:1)

通常情况下,在实例而不是类上设置__mul__根本不起作用,但MockMagicMock允许您这样做。问题是,mock1.__mul__是一个绑定方法,或者至少它应该表现得像一个。这意味着它被称为

mock1.__mul__(mock2)

不是mock1.__mul__(mock1, mock2)

您已将multiplicateMocks写为无约束方法。你需要绑定它:

mock1.__mul__.side_effect = multiplicateMocks.__get__(mock1)

答案 1 :(得分:0)

我认为MagicMock中已有的魔术方法会干扰你覆盖它们的尝试。

使用标准Mock可能会有更好的运气......

from unittest.mock import Mock

mock1 = Mock(name="mock1")
mock2 = Mock(name="mock2")

def multiplicateMocks(self, other):
    mock_name = str(self.name) + '*' + str(other.name)
    return Mock(name=mock_name)

mock1.__mul__ = multiplicateMocks

mock1*mock2

返回的结果字符串是

<Mock name="<Mock name='mock1.name' id='2175954027520'>*<Mock name='mock2.name' id='2175954027856'>" id='2175954027464'>