如何在pytest单元测试中替换函数内部的变量?
用pytest Mock os.listdir实现单元测试
这事儿用pytest自带的monkeypatch工具或者Python标准库的unittest.mock都能轻松搞定,我给你两种常用的实现方式,你按需选择:
方法一:使用pytest的monkeypatch(推荐,pytest原生支持)
monkeypatch是pytest专门用来修改/替换对象属性的工具,非常适合这类替换系统函数返回值的场景。
假设你的find_files函数大概是这样的:
import os def find_files(path): path_dir = os.listdir(path) # 这里是你的业务逻辑,比如筛选txt文件 return [file for file in path_dir if file.endswith('.txt')]
对应的测试代码可以这么写:
import os from your_module import find_files # 替换成你的函数所在模块 def test_find_files_with_monkeypatch(monkeypatch): # 定义一个mock版的listdir,返回我们预设的测试列表 def mock_listdir(_): # 这里的参数_可以忽略,或者如果需要验证路径的话也可以用 return ['whatever1.txt', 'whatever2.txt', 'whatever3.txt'] # 用mock函数替换真实的os.listdir monkeypatch.setattr(os, 'listdir', mock_listdir) # 调用要测试的函数 result = find_files('/随便写个测试路径就行') # 断言结果符合预期 assert result == ['whatever1.txt', 'whatever2.txt', 'whatever3.txt']
方法二:使用unittest.mock.patch
如果你习惯用Python标准库的mock工具,也可以用patch上下文管理器或者装饰器来实现:
from unittest import mock from your_module import find_files def test_find_files_with_mock(): # 用patch临时替换os.listdir with mock.patch('os.listdir') as mock_listdir: # 设置mock函数的返回值 mock_listdir.return_value = ['whatever1.txt', 'whatever2.txt', 'whatever3.txt'] # 测试函数 result = find_files('/测试路径') # 验证结果 assert result == ['whatever1.txt', 'whatever2.txt', 'whatever3.txt'] # 还可以额外验证os.listdir是否被正确调用(比如传入的路径是否正确) mock_listdir.assert_called_once_with('/测试路径')
重要注意事项
如果你的find_files函数是在某个模块(比如my_utils.py)里导入的os,那mock的时候要写模块内的os路径,比如:
# 错误写法:mock全局的os.listdir with mock.patch('os.listdir'): ... # 正确写法:mock my_utils模块里的os.listdir with mock.patch('my_utils.os.listdir'): ...
这是因为mock是作用于被测试代码实际导入的对象,而不是全局的os模块,这点很容易踩坑!
内容的提问来源于stack exchange,提问作者Damian Silkowski
相关产品推荐
相关产品推荐

