如何使用Pytest模拟在Python模块的全局范围内调用的函数?

3

我已经在“sample.py”中编写了以下函数,在“test_sample.py”中编写了相应的测试脚本。主要函数roll_dice在名为“dice.py”的模块中。所有这些文件都在名为“myapp”的文件夹中。

场景1

dice.py

import random
def roll_dice():
    print("rolling...")
    return random.randint(1, 6)

sample.py

from myapp.dice import roll_dice
def guess_number(num):
    result = roll_dice()
    if result == num:
        return "You won!"
    else:
        return "You lost!"

test_sample.py

@mock.patch("myapp.sample.roll_dice")
def test_guess_number(mock_roll_dice):
    mock_roll_dice.return_value = 3
    assert guess_number(3) == "You won!"

当我使用 Pytest 运行测试时,它可以正常运行。但是当我对下面的 sample.py 文件进行小改动后,测试失败了: 场景 2 sample.py
from myapp.dice import roll_dice
result = roll_dice() # Here is the change
def guess_number(num):
    if result == num:
        return "You won!"
    else:
        return "You lost!"

其余的都不变!

当我在 sample.py 模块的全局作用域中调用函数而不是在另一个函数内部调用它时,测试会失败。 有人能告诉我如何在方案二中模拟 roll_dice 函数吗?

我猜想我们无法在模块的全局作用域中模拟函数调用。这正确吗?

2个回答

4
在方案2中,roll_dice在导入时被调用。 完整的test_sample.py应为:
from myapp.sample import guess_number      # Call to `roll_dice` is done here
                                           # before mock

@mock.patch("myapp.sample.roll_dice")
def test_guess_number(mock_roll_dice):
    mock_roll_dice.return_value = 3
    assert guess_number(3) == "You won!"

如果您将import放在test函数内部,它也不起作用,因为patch(“myapp.sample.roll_dice”)会在mocking之前导入myapp.sample

可以使用以下方法解决:

@mock.patch("myapp.dice.roll_dice")
def test_guess_number(mock_roll_dice):
    from myapp.sample import guess_number  # Call to `roll_dice` is done here
                                           # You shouldn't have imported `myapp.sample`
                                           # before
    mock_roll_dice.return_value = 3
    assert guess_number(3) == "You won!"

但是要小心在导入时执行的代码(全局变量初始化)。最终你测试的只是你对模拟库的了解程度。


-1

执行顺序如下:

  1. 从test_sample.py中导入sample.py
  2. 初始化全局变量result
  3. 使用mock.patch修补roll_dice函数
  4. 执行测试函数

当你从test_sample.py中导入sample.py时,全局变量result的值将被初始化,但是patching函数roll_dice需要等待测试fixture初始化。

在mock.patching之前,results总是被初始化,因此该值始终来自原始函数而不是模拟函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接