【问题标题】:How to best mock module-level function reference in python如何在 python 中最好地模拟模块级函数引用
【发布时间】:2021-09-02 06:52:26
【问题描述】:

我有一个 Python 模块,其设置大致如下:

from external_module import fn_a, fn_b

options = {
  "a": fn_a
  "b": fn_b
}

def foo(bar):
  options[bar]()

我现在想写一个测试,从外部模块调用正确的函数:

from my_module import foo

@mock.patch("external_module.fn_a")
@mock.patch("external_module.fn_b")
def test_foo(mock_a: MagicMock, mock_b: MagicMock):
  foo("a")
  foo("b")

  mock_a.assert_called_once()
  mock_b.assert_called_once()

现在因为 options 是在模块级别创建的,并且导入发生在函数被模拟出来之前,所以测试失败。

到目前为止,我提出了两个解决方案:

  1. 将函数调用包装在lambda
options = {
  "a": lambda : fn_a()
  "b": lambda : fn_b()
}
  1. 在测试函数中导入模块:
@mock.patch("external_module.fn_a")
@mock.patch("external_module.fn_b")
def test_foo(mock_a: MagicMock, mock_b: MagicMock):
  from my_module import foo
  foo("a")
  foo("b")

到目前为止,我倾向于后一种解决方案,但我想知道是否有其他方法可以做到这一点?

【问题讨论】:

    标签: python unit-testing mocking pytest python-unittest


    【解决方案1】:

    我已经意识到如果有多个类似的测试,选项 2 不起作用,因为导入在同一次运行中只发生一次。由此产生的修复也是我现在首选的解决方案:

    import my_module
    from importlib import reload
    
    @mock.patch("external_module.fn_a")
    @mock.patch("external_module.fn_b")
    def test_foo(mock_a: MagicMock, mock_b: MagicMock):
      reload(my_module)
      my_module.foo("a")
      my_module.foo("b")
    
      mock_a.assert_called_once()
      mock_b.assert_called_once()
    

    【讨论】:

      猜你喜欢
      • 2019-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-05
      • 2011-11-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多