繁体   English   中英

为什么python mock.patch在使用第二个补丁参数vs return_value时工作方式不同?

[英]Why does python mock.patch work differently when second patch argument is used vs return_value?

我试图模拟一个依赖方法的返回值,但返回值在使用return_value和向mock.patch添加一个额外的参数之间是不同的。 请帮我弄清楚原因。 我尝试在线搜索,但找不到答案。

库/ abc.py:

from tools.operating_system import os_name

class ABC(object):    
    def get_os_info(self):
        return os_name()

工具/ operating_system.py:

import os

def os_name():
    return os.name

库/ test_abc.py:

from unittest import TestCase, mock
from library.abc import ABC

class TestMain(TestCase):
    # This works because the name method returns `test`
    def test_mocking_os_name(self):
        with mock.patch('tools.operating_system.os.name', 'test'):
            abc = ABC()
            res = abc.get_os_info()
            self.assertEqual(res, 'test')

    # The test fails because the name method returns `<MagicMock name='name' id='4515046400'>`
    def test_mocking_os_name(self):
        with mock.patch('tools.operating_system.os.name') as mock_name:
            mock_name.return_value = 'test'
            abc = ABC()
            res = abc.get_os_info()
            self.assertEqual(res, 'test')

注意:这个例子有点人为,因为我可以模拟os_name方法。 这不是主要问题。 我正在尝试学习python测试模拟,我希望能够模拟os.name 谢谢! 这适用于Python 3.7.2但我在Python 2.7.15中遇到了同样的问题

请参阅mock.patch的文档:当您调用它时

with mock.patch('tools.operating_system.os.name', 'test')

您正在执行此操作:

with mock.patch('tools.operating_system.os.name', NEW='test')

您将用字符串test替换os.name ,这样可以正常工作。

当你打电话给这个

with mock.patch('tools.operating_system.os.name') as mock_name:

您正在执行此操作:

with mock.patch('tools.operating_system.os.name', NEW=DEFAULT) as mock_name:

您将NEW保留为NEW=DEFAULT因此os.name设置为MagicMock对象(如文档所述)。 设置mock_name.return_value='test'不起作用,因为你没有在代码中的任何地方调用函数os.name() ,当然你也不应该这样,因为os.name是一个字符串而不是一个函数。

就像您说的那样,在实际代码中,您需要修补os_name函数而不是os.name

def test_patching_os_name(self):
    with mock.patch('library.abc.os_name') as mock_os_name:
        mock_os_name.return_value = 'test'
        abc = ABC()
        res = abc.get_os_info()
        self.assertEqual(res, 'test')

此测试不依赖于os_name函数的内部实现 如果ABC类的正确行为依赖于os_name总是返回os.name (这是测试所断言的),那么该类也可以使用os.name本身而不依赖于tools.operating_system

最终,我有一点个人偏爱:我更喜欢注入依赖项,而不是尽可能地打补丁,例如,参见文章“每个嘲笑.patch()都有点气味”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM