如何用多个补丁动态装饰python unittest class

How to dynamically decorate python unittest class with multiple patches

函数在source.py中定义并在use_source.py中调用。我从 test.py 打补丁

source.py

def example_function():
    print("I don't want this to run")

use_source.py

from source import example_function

def call_example_function():
    example_function()

test.py

import unittest
from unittest.mock import patch
import use_source

file_names = ["use_source.example_function"]


def fake_function():
    print("I want this to run instead")


@patch(file_names[0], new=fake_function)
class ExampleTest(unittest.TestCase):

    def test_example(self):
        use_source.call_example_function()


if __name__ == '__main__':
    unittest.main()

但是,我有多个像 use_source.py 这样的文件需要修补,所以这是我的问题

如何在给定目标列表的情况下动态调用补丁装饰器?

我正在寻找类似这样的东西

@patch_list(file_names, new=fake_function)
class ExampleTest(unittest.TestCase):

我可以做到这一点,但我有大量不同数量的文件需要修补

@patch(file_names[0], new=fake_function)
@patch(file_names[1], new=fake_function)
class ExampleTest(unittest.TestCase):

最后,我正在寻找一个只修改 test.py

的解决方案

我可以使用装饰器,但在测试的 SetupClass 方法中使用 patch.start()

import unittest
from unittest.mock import patch
import use_source

file_names = ["use_source.example_function"]


def fake_function():
    print("I want this to run instead")

class ExampleTest(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        for file_name in file_names():
            patch(file_name, new=fake_function).start()

    def test_example(self):
        use_source.call_example_function()


if __name__ == '__main__':
    unittest.main()

运行 python test.py 产生与上面相同的输出,并允许我修补大量不同的方法!

装饰器语法只是函数应用的语法糖。你可以写

class ExampleTest(unittest.TestCase):
    ...

for f in file_names:
    ExampleTest = patch(f, new=fake_function)(ExampleTest)

我不确定这种方法与您找到的解决方案之间是否存在显着差异。