模拟函数在python中的函数dict中

时间:2017-07-05 18:58:12

标签: python python-2.7 unit-testing mocking

假设我有一个如下所示的类:

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

如何模拟从函数dict调用的函数?

1 个答案:

答案 0 :(得分: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')