【问题标题】:Mock functions in a function dict in pythonpython中函数dict中的模拟函数
【发布时间】:2017-07-05 18:58:11
【问题描述】:

假设我有一个如下声明的类:

class SampleClass(object):
    def __init__(self):
       self.ops = {
           'key 1': self.function_a,
           'key 2': self.function_b
       }

    def function_a(self):
      print('Inside a')

    def function_b(self):
      print('Inside b')

    def main(self, key):
       self.ops[key]()

根据我得到的密钥,我选择并执行这两个函数中的任何一个。

我正在尝试对主要功能进行单元测试,但我无法修补 function_afunction_b

我正在一个名为 test.py 的单独文件中编写单元测试。

当我尝试用:修补 function_a 时:

self.sampleclass = SampleClass()
with patch.object(SampleClass, 'function_a', return_value=None) as test_function:
    self.sampleclass.main('key1')

控制进入function_a 并打印Inside a

如何模拟从函数字典调用的函数?

【问题讨论】:

  • 那个例子行不通。但如果是这样,我不会模拟那些也是被测类的一部分的方法。它们是有效的实现细节,通过调用 main 对其进行测试,并确保您从真实方法中获得预期值。
  • @jonrsharpe 我在函数字典中的函数之前错过了 self 关键字。现在更正了。该代码现在可以工作了。但是我无法在不调用 function_a 的情况下对主函数进行单元测试。对我来说 function_a 是一个需要身份验证和其他东西的 API,所以我宁愿不调用它。
  • 可以依次模拟function_a(其实是方法)调用的东西;在这种情况下,嘲笑print 就可以了。例如,如果您使用 requests 从它发出 API 请求,请查看 responses 库。但是不要模拟方法本身;单位是SampleClass,而不是单独的main方法。

标签: python python-2.7 unit-testing mocking


【解决方案1】:

可以修补字典条目,这是一个与您发布的非常相似的示例:

from mock import patch, Mock

class SampleClass():
    def __init__(self):
        self.ops = {
            'key 1': self.function_a,
            'key 2': self.function_b
        }

    def function_a(self):
        print('Inside a')

    def function_b(self):
        print('Inside b')

    def main(self, key):
        self.ops[key]()

test_function = Mock(name='mock_a')

sampleclass = SampleClass()
with patch.dict(sampleclass.ops, {'key 1': test_function}):
    sampleclass.main('key 1')

    test_function.assert_called_once()

我认为您也可以通过在创建 SampleClass 的实例之前修补它来解决您的问题。

但是,我建议您考虑模拟 function_a() 的一部分,而不是试图模拟整个事情。这将更容易理解,并且可能将模拟对象置于被测系统与其依赖项之间的更好接缝处。

例如,假设您的 SampleClass 需要模拟,因为它登录到 Web 服务,然后发送多个请求。如果function_a() 在发出这些请求之前调用self.login(),那么您可以模拟SampleClass.login()

from mock import patch

class SampleClass():
    def __init__(self):
        self.ops = {
            'key 1': self.function_a,
            'key 2': self.function_b
        }

    def login(self):
        session = None
        # session = service.login(username, password)
        return session

    def function_a(self):
        session = self.login()
        session.send('Inside a')

    def function_b(self):
        session = self.login()
        session.send('Inside b')

    def main(self, key):
        self.ops[key]()

sampleclass = SampleClass()
with patch('__main__.SampleClass.login') as test_function:
    sampleclass.main('key 1')

    test_function.assert_called_once()
    test_function.return_value.send.assert_called_once_with('Inside a')

【讨论】:

    猜你喜欢
    • 2014-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    • 2019-02-04
    • 1970-01-01
    相关资源
    最近更新 更多