如何在函数中模拟函数。是不是可以使用两个或多个补丁来模拟函数中的函数调用?

Posted

技术标签:

【中文标题】如何在函数中模拟函数。是不是可以使用两个或多个补丁来模拟函数中的函数调用?【英文标题】:How to mock a function within a Function. Is it possible to use two or more Patches to mock a function call within a Function?如何在函数中模拟函数。是否可以使用两个或多个补丁来模拟函数中的函数调用? 【发布时间】:2021-12-31 03:06:34 【问题描述】:

我需要模拟一个函数 (funk) 调用,该调用依赖于在此函数 (funk) 中调用的另外两个函数的返回值。是否可以使用超过 1 个 Patch 来模拟两个被调用函数的返回值。

要测试/模拟的 API:

from subprocess import check_output


def get_value_a(value_a: int):  
    return value_a  

def get_value_b(value_b: int):  
    return value_b  

def print_contents_of_cwd(val_a, val_b):  
    if val_a > 0:  
        return check_output(['ls']).split()  
    else:  
        return val_b  

我正在尝试使用两个补丁来模拟两个函数(get_value_aget_value_b)的返回值,如下所示:

from Mack_Test_Practise import list_dir
from unittest import mock, TestCase


class TestExamples(TestCase):
    # Using Decorator Method

    @mock.patch('Mack_Test_Practise.list_dir.check_output',
                return_value=b'list_dir.py')
    @mock.patch('Mack_Test_Practise.list_dir.get_value_a',
                return_value=5)
    @mock.patch('Mack_Test_Practise.list_dir.get_value_b',
                return_value=3)
    def test_print_contents_of_file(self, mock_check_output,val_a, val_b):
        actual_result = list_dir.print_contents_of_cwd(val_a, val_b)
        print("actual_result", actual_result)

        expected_result = b'list_dir.py'
        self.assertIn(expected_result, actual_result)  
  

当我运行测试时,会抛出以下错误。

Error  
Traceback (most recent call last):  
  File "/usr/lib/python3.6/unittest/mock.py", line 1183, in patched  
    return func(*args, **keywargs)
  File  
 "/home/shyam/PycharmProjects/pythonProject/Mock_Test/test_list_dir.py", line 15, in test_print_contents_of_file
    actual_result = list_dir.print_contents_of_cwd(val_a, val_b)
  File "/home/shyam/PycharmProjects/pythonProject/Mack_Test_Practise/list_dir.py", line 13, in print_contents_of_cwd  
    if val_a > 0:  
**TypeError: '>' not supported between instances of 'MagicMock' and 'int'**  

我的第一个问题是,是否允许像我一样使用多个补丁? 我的第二个问题是为什么我们会收到类型错误,因为它是 Python 中的合法运算符。 请提出解决方案。

感谢一百万和最好的问候!!

【问题讨论】:

【参考方案1】:

这样使用多个补丁是合法的。

我认为您的问题是因为您已经修补了一个函数,并试图将修补后的函数与一个整数进行比较。您在 mock 中设置了返回值,但您仍然需要调用它来获取该返回值。

actual_result = list_dir.print_contents_of_cwd(val_a(), val_b())

注意val_a()val_b() 中包含的括号

现在,由于这些不再是值,而是函数(从技术上讲,它们是 MagicMock 对象,但它们正在替换函数)我建议将它们重命名为 get_val_a()get_val_b() 以便您的意图更清楚。

【讨论】:

感谢您的接受。为了将来参考,通常最好等一天左右,这样其他用户(可能在不同时区)也不会气馁提供答案。 最后一个问题,是否可以模拟私有函数?喜欢 __download_file 吗? 是的,有可能。查看docs.python.org/3/tutorial/classes.html 并搜索“mangling”以获取有关 python 如何使用前导双下划线更改方法名称的信息。 也就是说。需要弄乱私有变量/方法通常是一种反模式。考虑是否最好重构您的代码,或者以不需要访问私有的方式重新设计它。 (我知道这只是为了测试,但即使如此,通常也有更好的方法。)

以上是关于如何在函数中模拟函数。是不是可以使用两个或多个补丁来模拟函数中的函数调用?的主要内容,如果未能解决你的问题,请参考以下文章

Python模拟补丁在另一个函数内的一个函数

如何在单个 C# 函数中为两个或多个不同的变量使用相同的名称? [关闭]

我可以在包装函数之前修补 Python 装饰器吗?

C++,怎么让程序模拟用户输入指令,并自行回车以执行该指令(不是写个输出函数只做样子)?

如何实现JS函数的重载

手动设置函数地址 gcc