我在弄清楚如何使用MagicMock的side_effect属性时遇到了问题,但它似乎只有在我为函数打补丁时才有效。然而,我想修补属性。下面是一个最小的代码示例:
# in calendar.py
class Weeks():
a = property(lambda self: 0)
b = property(lambda self: 0)
c = property(lambda self: 0)
@patch('calendar.Weeks')
def test_something_else(weeks_mock):
weeks_mock.return_value.a.side_effect = [0, 10, 20, 30]
weeks_mock.return_value.b = 40
weeks_mock.return_value.c = 50
# some more code...我也尝试过像这样使用PropertyMock,但没有成功:
@patch('calendar.Weeks')
def test_something_else(weeks_mock):
type(weeks_mock).a = PropertyMock(side_effect=[0, 10, 20, 30])
weeks_mock.return_value.b = 40
weeks_mock.return_value.c = 50
# some more code...我将非常感谢任何意见!
发布于 2018-08-15 20:05:28
使用
__get__模拟和测试类属性
获取描述
调用以获取所有者类的属性(类属性访问)或该类的实例的属性(实例属性访问)。
with mock.patch.object(Weeks, 'a') as mock_a:
mock_a.__get__ = mock.Mock(return_value='mocked_cls_attr')
self.assertEqual(Weeks.a, 'mocked_cls_attr')不确定你为什么会得到这个错误,这里有一个有效的测试来帮助你找出错误。
import unittest
import mock
class Weeks():
a = property(lambda self: 0)
b = property(lambda self: 0)
c = property(lambda self: 0)
class TestWeeks(unittest.TestCase):
@mock.patch.object(Weeks, 'a')
@mock.patch.object(Weeks, 'b')
@mock.patch.object(Weeks, 'c')
def test_something_else(self, mockc, mockb, mocka):
# the attr a now mocka is becoming a function using side_effect
mocka.side_effect = [0, 10, 20, 30]
mockb.__get__ = mock.Mock(return_value=40)
mockc.__get__ = mock.Mock(return_value=50)
# mocka() not mocka as it is a function now
self.assertEqual(mocka(), 0)
self.assertEqual(mocka(), 10)
week = Weeks()
self.assertEqual(week.b, 40)
self.assertEqual(week.c, 50)
# week.a with using function will trigger a failure
# AssertionError: <MagicMock name='a' id='139943677051600'> != 20
self.assertEqual(week.a(), 20)
def test_property(self):
# no need to mock a property object, just replace it
week = Weeks()
week.a = property(lambda self: 1)
self.assertTrue(isinstance(week.a, property))
self.assertEqual(week.a.fget(0), 1)运行测试:
nosetests -v python2_unittests/tests/test_cls_attr.py结果:
test_something_else (python2_unittests.tests.test_cls_attr.TestWeeks) ... ok发布于 2020-10-02 18:54:09
如果您将其作为new_callable传递给每个属性的patch,则PropertyMock将起作用:
class Weeks():
a = property(lambda self: 0)
b = property(lambda self: 0)
c = property(lambda self: 0)
@patch('__main__.Weeks.a', new_callable=PropertyMock)
@patch('__main__.Weeks.b', new_callable=PropertyMock)
@patch('__main__.Weeks.c', new_callable=PropertyMock)
def test_something_else(mock_c, mock_b, mock_a):
mock_a.side_effect = [0, 10, 20, 30]
mock_b.return_value = 40
mock_c.return_value = 50
# some more code...
weeks = Weeks()
assert weeks.a == 0
assert weeks.a == 10
assert weeks.b == 40
assert weeks.c == 50实际上,您的PropertyMock示例适用于a。我只需要调整b和c,让它完全正常工作:
@patch('__main__.Weeks')
def test_something_else(weeks_mock):
type(weeks_mock).a = PropertyMock(side_effect=[0, 10, 20, 30])
type(weeks_mock).b = PropertyMock(return_value=40)
type(weeks_mock).c = PropertyMock(return_value=50)
# some more code...
assert weeks_mock.a == 0
assert weeks_mock.a == 10
assert weeks_mock.b == 40
assert weeks_mock.c == 50如果您需要更复杂的逻辑,可以直接打补丁到新的property
@patch('__main__.Weeks.a', property(lambda self: 40 if self.b else 50))
def test_something_complicated():
# some more code...
weeks = Weeks()
assert weeks.a == 50https://stackoverflow.com/questions/51852648
复制相似问题