【问题标题】:How to dynamically decorate python unittest class with multiple patches如何用多个补丁动态装饰python unittest类
【发布时间】:2022-01-09 23:24:50
【问题描述】:

一个函数在 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的解决方案

【问题讨论】:

    标签: python dynamic python-unittest python-decorators


    【解决方案1】:

    我可以使用装饰器,但在测试的 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 产生与上面相同的输出,并允许我修补大量不同的方法!

    【讨论】:

      【解决方案2】:

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

      class ExampleTest(unittest.TestCase):
          ...
      
      for f in file_names:
          ExampleTest = patch(f, new=fake_function)(ExampleTest)
      

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

      【讨论】:

      • 谢谢,但是使用上面的代码,我要么得到一个“分配前引用的局部变量'ExampleTest'”,要么不应用补丁,即打印“我不希望它运行”
      • 我看不出局部变量错误的任何原因。你是把循环放在类语句中,还是放在之后? (应该在之后,如图所示。)
      • 是的,局部变量错误出现在类语句中,但是如果我将循环放在类语句之后,则不会应用补丁
      猜你喜欢
      • 2017-01-31
      • 1970-01-01
      • 1970-01-01
      • 2022-12-09
      • 2020-11-26
      • 2021-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多