小能豆

mockers 和 pytest 函数补丁中的错误

py

我正在尝试使用 pytest 和 mocker 来测试我正在编写的 python 包。这是我的 repo 的概要(假设包名为hoopla

hoopla
|- library
  |- __init__.py
  |- general
  |- exceptions
  |- bourhaha 
|- tests
  |- __init__.py
  |- test_brouhaha

里面general.py有一些可以通过包和包内文件使用的函数。例如:

  • general.py包含函数validate_email_exists()
  • brouhaha.py包含一个名为 的函数create_username(),该函数调用函数validate_email_exists()

在测试函数时,test_brouhaha.py我想在它调用外部系统时模拟调用。 当我尝试使用 pytest 和 pytst-mock 模拟此调用时,出现错误“无模块…”(见下文)。validate_email_exists()``create_username()

# general.py

def validate_email_exists(email):
  return True
# bourhaha.py

from .general import validate_email_exists

def create_username(email):
  if not validate_email_exists(email):
    return False
  # create usename
  return True
# test_bourhaha.py

from library.bourhaha import *

def test_create_username(mocker):
  mock_email_exists = mocker.patch("library.bourhaha.general.validate_email_exists") # causes error
---
  mock_email_exists = mocker.patch("library.general.validate_email_exists") # causes error
  mock_email_exists.return_value = False
  assert create_username("test") # Fails because value of validate_email_exists return True
---

在我的代码中我最初模拟了

mock_email_exists = mocker.patch("library.brouhaha.general.validate_email_exists")
mock_email_exists.return_value = False

这会引发错误

ModuleNotFoundError: No module named 'library.brouhaha.general'; 'library.brouhaha' is not a package

当我尝试

mock_email_exists = mocker.patch("library.general.validate_email_exists")
mock_email_exists.return_value = False

没有错误,但是测试失败,因为函数返回 True


阅读 16

收藏
2025-01-09

共1个答案

小能豆

修补位置

问题出在patch()函数使用的路径上。正确的路径是:

# CORRECT PATCHING
mock_email_exists = mocker.patch("library.bourhaha.validate_email_exists")

请参阅文档中的修补位置patch()以了解有关正确使用的其他详细信息。

在您的情况下,文件general.py定义了函数validate_email_exists,但文件bourhaha.py执行import指令:

from .general import validate_email_exists

因此它会validate_email_exists在其命名空间中创建一个名称。您必须更改此名称指向的对象。使用您patch()已在定义对象的地方更改了该对象。

回到你的代码

在您的代码中,您将 设置为return_value。此时您还必须更改指令,因为函数返回时函数会返回。mock_email_exists``False``assert``create_username()``False``validate_email_exists()``False

因此正确的测试函数是:

from library.bourhaha import *

def test_create_username(mocker):
    # WATCH to the path = 'library.bourhaha.validate_email_exists'
    mock_email_exists = mocker.patch("library.bourhaha.validate_email_exists")
    mock_email_exists.return_value = False
    # I have change the assert test (assert ---> assert not)
    assert not create_username("test")

您的模块general.py非常bourhaha.py完美。

2025-01-09