【问题标题】:python mock get calling objectpython mock 获取调用对象
【发布时间】:2012-05-29 13:58:29
【问题描述】:

我有一个UUT 类实例化Worker 对象,并调用它们的do_stuff() 方法。
Worker 对象将Provider 对象用于两件事:

  1. 调用提供者对象上的方法来做一些事情
  2. 通过订阅提供程序事件的方法从提供程序获取通知

当工作人员收到通知时,它会对其进行处理,并通知UUT 对象,作为响应,该对象可以创建更多Worker 对象。

我已经单独测试了每个类,我想一起测试UUT+Worker。为此,我打算模拟出Provider

import mock
import unittest
import provider

class Worker():
    def __init__(self, *args):
        resource.default_resource.subscribe('on_spam', self._on_spam) # I'm going to patch 'resource.default_resource'

    def do_stuff(self):
        self.resource.do_stuff()

    def _on_spam(self, message):
        self._tell_uut_to_create_more_workers(message['num_of_new_workers_to_create'])


class UUT():
    def __init__(self, *args):
        self._workers = []

    def gen_worker_and_do_stuff(self, *args)
       worker = Worker(*args)
       self._workers.append(resource)
       worker.do_stuff()


class TestCase1(unittest.TestCase):

    @mock.patch('resource.default_resource', spec_set=resource.Resource)
    def test_1(self, mock_resource):
        uut = UUT()
        uut.gen_worker_and_do_stuff('Egg')   # <-- say I automagically grabbed the resulting Worker into self.workers
        self.workers[0]._on_spam({'num_of_new_workers_to_create':5}) # <-- I also want to get hold of the newly-created workers

有没有办法获取uut 生成的工作对象,而不直接访问uut 中的_workers 列表(这是一个实现细节)?

我想我可以在Worker.__init__ 中做到这一点,工作人员订阅提供者事件,所以我想问题简化为:
如何在调用resource.default_resource.subscribe('on_spam', self._on_spam)时提取被调用方中的self

【问题讨论】:

  • 你想要的都是不可能的。如果 API 不可测试,请更改它。
  • 或者您可以修补 Worker 类。
  • @ms4py - 我确实在单元测试阶段修补了Worker 类。现在我正在做集成测试,我希望看到整个堆栈一起工作
  • @bavaza 你想测试这段代码的哪个方面?
  • @bereal - 请查看更新。

标签: python mocking patch


【解决方案1】:

作为依赖倒置原则的应用,我会将Worker 类作为依赖传递给UUT

class UUT():
    def __init__(self, make_worker=Worker):
        self._workers = []
        self._make_worker = make_worker

    def gen_worker_and_connect(self, *args)
       worker = self._make_worker(*args)
       self._workers.append(resource)
       worker.connect()           

然后提供您想要从测试中获得的任何内容,而不是 Worker。这个自己的函数可以与测试范围共享创建的对象。除了解决这个特定问题之外,这还将使依赖项显式且独立于 UUT 实现。而且您也不需要模拟资源事物,这使得测试依赖于与被测类无关的事物。

【讨论】:

  • 您可以通过直接修补 Worker 类来实现相同的目的。我不建议在 Python 中使用工厂函数。
  • @bereal - 在我的情况下无法注射 - 请参阅我添加的说明。
  • @ms4py 这取决于使用的方法。在 TDD 中,DI 总是比任何类型的补丁更可取,因为(简而言之)测试不应该知道实现,所以补丁是一种设计味道。在非 TDD 中......好吧,作为一个 TDD 粉丝,我不会用长棍子触及这个话题。
猜你喜欢
  • 2011-12-01
  • 1970-01-01
  • 2017-04-02
  • 2016-07-05
  • 2018-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多