【问题标题】:Revisited: Python Mocking a function from an imported module重温:Python 从导入的模块中模拟一个函数
【发布时间】:2022-01-09 12:21:50
【问题描述】:

Python 3.9.
在我的单元测试中,我想实例化 ServiceProvider,但它必须在测试中使用 mock_get_service,而不是导入的 get_service,因为这会进行网络调用。

我已经尝试了许多解决方案,包括上面提到的原始解决方案,但都没有成功。每次都会调用原来的 get_service 并崩溃。

app_module:

from services import get_service

class ServiceProvider()

    def find_service(self, service_id):
        return get_service(service_id)

单元测试模块:

from app_module import ServiceProvider

def mock_get_service(service_id):
    """ Test method: return the named service. """
    if service_id == 'ServiceA':
        service = ServiceA()
    else:
        service = ServiceB()
    return service

class Test_ServiceProvider(unittest.TestCase):
    def test1_find_service(self):
        with patch('app_module.get_service') as mocked_get_service:
            mocked_get_service.side_effect = mock_get_service
            server = ServiceProvider()
            serv = server.find_service('ServiceA')
            self.assertIsInstance(serv, ServiceA)

【问题讨论】:

  • 为了简化这篇文章的代码,我将第一个 def 命名为 get_service,如果我将其命名为 find_service 会更清楚,如后所述。对不起。
  • 您可以阅读docs.python.org/3/library/unittest.mock.html#where-to-patch 了解有关如何模拟事物的更多信息。我觉得你的问题有点难以理解,因为不同的文件中有几个名称相似的函数,我不确定你到目前为止尝试了什么。
  • 我理解你的问题,我已经简化了问题。我想我正在尝试模拟导入到 app_module 中的 get_service,这就是我认为 ServiceProvider 中的调用会进行的情况。我尝试了很多安排都没有成功。非常感谢您的帮助。

标签: python unit-testing mocking


【解决方案1】:

在模拟对象成员时应该使用patch.object

with patch.object(ServiceProvider, "get_service", side_effect=mock_get_service):
    # your test case will use mock_get_service() when ServiceProvider.get_service() is called

【讨论】:

  • 此解决方案不适用于首选代码。我已经澄清了这个问题。
【解决方案2】:
from app_module import ServiceProvider

def mock_get_service(service_id):
    """ Test method: return the named service. """
    if service_id == 'ServiceA':
        service = ServiceA()
    else:
        service = ServiceB()
    return service

class Test_ServiceProvider(unittest.TestCase):
    def test1_find_service(self):
        with patch.object(ServiceProvider, "get_service", side_effect=mock_get_service):

            mocked_get_service.side_effect = mock_get_service
            server = ServiceProvider()
            serv = server.find_service('ServiceA')
            self.assertIsInstance(serv, ServiceA)

【讨论】:

  • ServiceProvider 没有 get_service 属性,get_service 是一个导入的方法。也许 mock 不会做我想要的。
猜你喜欢
  • 2013-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 2011-10-09
  • 2022-11-11
  • 2020-12-09
相关资源
最近更新 更多