简体   繁体   English

如何使用自身模拟.patch 函数?

[英]How to mock.patch a function with itself?

I am trying to replace a function with itself, using different parameters.我正在尝试使用不同的参数用它自己替换一个函数。

Here is a sample.这是一个示例。 I can't share the real code, I'm on papery secrecy!我不能分享真正的代码,我在纸上保密!

import unittest
from unittest.mock import patch

import mymodule
import production

class MyTest(unittest.TestCase):
    
    @patch('production.mymodule.myfunction', lambda: mymodule.myfunction(devmode=True))
    def test_main_with_mymodule_function_does_not_raise_exception(self):
        # This is an integration test. myfunction is used within main.
        try:
            production.main()
        except Exception as e:
            self.fail(e)

As expected the following generates a recursive call:正如预期的那样,以下生成递归调用:

@patch('production_code.mymodule.myfunction', lambda: mymodule.myfunction(devmode=True))

We basically decorate myfunction with a decorator that will call myfunction .我们基本上是装饰myfunction一个装饰,将调用myfunction We get a nice "Too many recursions" exception!我们得到了一个很好的“递归过多”异常!

I need a way to replace myfunction(devmode=False) with myfunction(devmode=True) .我需要一种用myfunction(devmode=True)替换myfunction(devmode=False) myfunction(devmode=True) But because I am in an integration test, and testing main() , I have no direct access to the function's parameters.但是因为我正在进行集成测试并测试main() ,所以我无法直接访问该函数的参数。 Thing is, I made this very integration test to test how myfunction integrates with everything else in main.事情是,我做了这个非常集成的测试来测试 myfunction 如何与 main.js 中的所有其他东西集成。

Ideally, I shouldn't even have to create a devmode parameter, but I'm running a heavy sql query that requires to be limited by adding "TOP(10)" to the query.理想情况下,我什至不必创建devmode参数,但我正在运行一个繁重的 sql 查询,需要通过向查询添加"TOP(10)"来进行限制。

Thanks for your help!谢谢你的帮助! :) :)

You can keep a reference to the unpatched function before your test runs.您可以在测试运行之前保留对未修补函数的引用。 Use that in the patch call:在补丁调用中使用它:

import unittest
from unittest.mock import patch


def iut(devmode=False):
    print(devmode)


class MyTest(unittest.TestCase):
    _unpatched = iut   # keep reference to unpatched IUT

    @patch('so_test.iut', lambda *args, **kwargs: MyTest._unpatched(devmode=True))
    def test(self):
        try:
            iut()
        except Exception as e:
            self.fail(e)

This results in the following, indicating devmode was set to True:结果如下,表明devmode设置为 True:

True

Note: you might need to pass args , kwargs to _unpatched depending in your function.注意:根据您的功能,您可能需要将argskwargs传递给_unpatched

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

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