Pytest Fixture模拟对象未传入被测函数,触发AssertionError
问题解决思路与修复方案
核心问题定位
- Mock未生效:被测代码直接导入并实例化
github.MainClass.Github,测试中的mock未正确拦截该导入路径 - Token类型错误:mock返回的git_token为整数
12121212,不符合Github构造函数对login_or_token的字符串类型要求 - 导入时机错误:测试代码在mock前就导入了被测模块,导致真实类被提前加载
- Fixture依赖问题:fixture依赖关系配置不当,mock未在被测代码执行前生效
具体修复步骤
1. 修正Mock路径,确保拦截正确
被测代码若通过from github import Github导入类,测试中需mock被测模块内的Github引用,而非原始类路径。比如被测模块为git_commons,则mock路径应为git_commons.Github。
示例代码:
from unittest.mock import patch, MagicMock import pytest from git_commons import GitCommons def test_read_template_from_git(): # 正确mock被测模块中的Github类 with patch('git_commons.Github') as mock_github: # 配置mock返回的仓库与内容 mock_repo = MagicMock() mock_file = MagicMock() mock_file.decoded_content = b'template content' mock_repo.get_contents.return_value = mock_file mock_github.return_value.get_repo.return_value = mock_repo # 执行被测逻辑 gc = GitCommons() result = gc.read_template_from_git() # 断言验证 mock_github.assert_called_once_with('12121212') # 传入字符串类型token assert result == 'template content'
2. 修正Token类型,返回字符串
确保mock获取git_token的逻辑返回字符串类型,若通过boto3获取token,需mock对应方法返回字符串:
@pytest.fixture def mock_boto3_session(): with patch('boto3.session.Session') as mock_session: mock_client = MagicMock() # 返回字符串类型的token mock_client.get_parameter.return_value = {'Parameter': {'Value': '12121212'}} mock_session.return_value.client.return_value = mock_client yield mock_session
3. 调整导入时机,保证Mock优先加载
若测试在mock前导入了git_commons,真实Github类会提前加载导致mock失效,可通过以下方式解决:
- 在测试函数内部导入被测模块
- 使用
patch装饰器,确保mock在模块导入前生效
示例(装饰器形式):
@patch('git_commons.Github') @patch('boto3.session.Session') def test_read_template_from_git(mock_session, mock_github): # 配置mock mock_client = MagicMock() mock_client.get_parameter.return_value = {'Parameter': {'Value': '12121212'}} mock_session.return_value.client.return_value = mock_client mock_repo = MagicMock() mock_file = MagicMock() mock_file.decoded_content = b'template content' mock_repo.get_contents.return_value = mock_file mock_github.return_value.get_repo.return_value = mock_repo # 延迟导入被测模块,确保mock已生效 from git_commons import GitCommons gc = GitCommons() result = gc.read_template_from_git() assert result == 'template content'
4. 修复Fixture依赖问题
使用autouse fixture确保mock在所有测试前自动激活,避免依赖配置错误:
@pytest.fixture(autouse=True) def mock_all(): with patch('git_commons.Github') as mock_github, patch('boto3.session.Session') as mock_session: # 配置boto3 mock mock_client = MagicMock() mock_client.get_parameter.return_value = {'Parameter': {'Value': '12121212'}} mock_session.return_value.client.return_value = mock_client # 配置Github mock mock_repo = MagicMock() mock_file = MagicMock() mock_file.decoded_content = b'template content' mock_repo.get_contents.return_value = mock_file mock_github.return_value.get_repo.return_value = mock_repo yield
关键注意事项
- Mock路径必须匹配被测代码中实际引用的类路径,这是Python mock生效的核心
- 严格保证传入参数类型符合被mock类的要求,比如Github的token必须为字符串
- 被测模块的导入时机必须晚于mock的初始化,否则真实类会提前加载导致mock失效
内容的提问来源于stack exchange,提问作者Srini
相关产品推荐
相关产品推荐

