Python单元测试:Pytest中Mock json.dumps()遇序列化错误的解决咨询
问题原因及解决方法
为什么会出现这个问题?
- Patch目标错误:mock的核心规则是patch被测试代码实际引用的那个对象,而非原始模块的对象。比如你测试代码里patch了
json.dumps,但如果被测试函数是在自身模块内导入json(比如import json写在被测试模块里),那实际调用的是该模块内的json.dumps引用,直接patch全局的json.dumps不会生效。 - Mock返回值不可序列化:默认情况下,
MagicMock实例本身不属于JSON可序列化类型。如果你的代码在调用json.dumps后,还有后续逻辑需要把返回值再次序列化(或传递给要求JSON格式的场景),就会触发TypeError。
其他patch能正常工作,是因为那些被mock的函数返回的MagicMock没有被后续代码要求做序列化操作,或者它们的返回值本身是基础类型(比如字符串、数字),不会触发序列化错误。
解决步骤
1. 确定正确的Patch目标
假设你的被测试代码在your_module.py里:
- 如果代码里是
import json后用json.dumps,就patchyour_module.json.dumps - 如果代码里是
from json import dumps后用dumps,就patchyour_module.dumps
2. 指定Mock的返回值或保留真实行为
方法一:直接指定返回值
如果只需要验证json.dumps的调用情况,不需要真实序列化,直接给mock指定合法的JSON字符串返回值:
from unittest import mock import pytest from your_module import your_function def test_your_function(): with mock.patch("your_module.json.dumps") as mock_dumps: # 指定返回值为合法JSON字符串 mock_dumps.return_value = '{"name": "test", "value": 123}' result = your_function({"name": "test", "value": 123}) # 验证调用参数和次数 mock_dumps.assert_called_once_with({"name": "test", "value": 123}) assert result == '{"name": "test", "value": 123}'
方法二:保留真实序列化行为
如果需要json.dumps正常工作,同时跟踪调用情况,可以用side_effect调用原始方法:
import json from unittest import mock from your_module import your_function def test_your_function_with_real_serialize(): with mock.patch("your_module.json.dumps") as mock_dumps: # 让mock调用原始的json.dumps方法 mock_dumps.side_effect = json.dumps result = your_function({"name": "test", "value": 123}) mock_dumps.assert_called_once_with({"name": "test", "value": 123}) assert result == '{"name": "test", "value": 123}'
方法三:Mock整个json库并指定dumps的返回值
如果要mock整个json库,需要给json.dumps单独指定返回值,而非依赖默认的MagicMock:
from unittest import mock import pytest from your_module import your_function def test_your_function_mock_whole_json(): with mock.patch("your_module.json") as mock_json: # 给dumps指定返回值 mock_json.dumps.return_value = '{"name": "test", "value": 123}' result = your_function({"name": "test", "value": 123}) mock_json.dumps.assert_called_once_with({"name": "test", "value": 123}) assert result == '{"name": "test", "value": 123}'
内容的提问来源于stack exchange,提问作者Pallavi
相关产品推荐
相关产品推荐

