如何设置和验证链式调用的 Python 模拟?

问题描述 投票:0回答:1

假设我想测试我的通话

Greeter
,这取决于第3方类
Foo
,而第3方类又取决于另一个类
Bar
。我需要模拟
Foo
,但是如何设置和验证链式调用
self.foo.get_bar().format(name)

greeter.py:

class Bar:

  def format(self, name):
    return name.upper()


class Foo:

  def __init__(self):
    self.bar = Bar()

  def get_bar():
    return self.bar


class Greeter:

  def __init__(self, foo):
    self.foo = foo

  def hi(self, name):
    return f'Hi {self.foo.get_bar().format(name)}'

PS:这个问题纯粹是关于Python mock的使用,而不是关于编写Python代码和测试的最佳实践,所以我不会重构代码。

python python-mock
1个回答
0
投票

经过一番研究,我找到了以下解决方案:

from unittest import mock
from unittest.mock import patch

import greeter
import unittest

class TestGreeter(unittest.TestCase):

  def setUp(self):
    self.foo_patcher = patch('greeter.Foo')
    self.foo_mock_class = self.foo_patcher.start()
    self.foo_mock = self.foo_mock_class()
    self.foo_mock.get_bar.return_value.format.return_value = 'EMY'

  def tearDown(self):
    self.foo_patcher.stop()

  def test_greeter(self):
    g = greeter.Greeter(self.foo_mock)

    result = g.hi('emy')

    self.assertEqual(result, 'Hi EMY')
    self.foo_mock.get_bar.return_value.format.assert_called_once_with('emy')
    self.foo_mock.get_bar.return_value.assert_has_calls([mock.call.format('emy')])
    self.foo_mock.assert_has_calls([mock.call.get_bar(), mock.call.get_bar().format('emy')])


if __name__ == '__main__':
    unittest.main()
© www.soinside.com 2019 - 2024. All rights reserved.