如何单元测试json.dumps及文件写入?JsonWriter类测试咨询
问题翻译
我正在测试自定义的JsonWriter类及其write_json方法,该方法接收API返回的数据并写入JSON文件。目前仅模拟了方法正常执行的返回结果,但我认为这种测试方式并不正确。想咨询是否需要将write_json拆分为更小的单元,或是存在更合适的测试方法?附上相关代码:
import json class JsonWriter: def write_json(self, weights, filename): try: json_data = json.dumps(weights, indent=4) with open(filename, 'w') as f: f.write(json_data) f.close() except Exception as e: return False, e return True, None
当前测试代码:
class JsonWrite(unittest.TestCase): @patch("argo_connectors.io.jsonwrite.JsonWriter.write_json") def test_read_file_data(self, mock_write_json): mock_write_json.return_value = True, None if __name__ == '__main__': unittest.main()
问题分析
你当前的测试完全没意义——直接mock了要测试的write_json方法本身,等于只是验证mock的返回值,根本没触及实际的业务逻辑(序列化数据、写入文件这些核心步骤)。不需要拆分这个方法,它的职责足够单一,只需要换一种测试思路,针对方法的依赖和实际行为做验证。
两种可行的测试方案
方案1:Mock依赖项,验证调用逻辑
这个方法适合快速验证方法是否正确调用了序列化和文件写入的逻辑,不用操作真实文件。需要mockjson.dumps和内置的open方法:
import unittest from unittest.mock import patch, mock_open from your_module import JsonWriter # 替换成你的实际模块名 class TestJsonWriter(unittest.TestCase): def test_write_json_success(self): test_data = {"key": "value", "num": 123} test_filename = "test.json" # Mock json.dumps,捕获是否被正确调用 with patch("json.dumps") as mock_dumps: mock_dumps.return_value = '{"key": "value", "num": 123}' # Mock open方法,模拟文件写入 with patch("builtins.open", mock_open()) as mock_file: writer = JsonWriter() result, error = writer.write_json(test_data, test_filename) # 验证返回值正确 self.assertEqual(result, True) self.assertIsNone(error) # 验证json.dumps被正确调用,参数符合预期 mock_dumps.assert_called_once_with(test_data, indent=4) # 验证文件被以写入模式打开,且写入了序列化后的内容 mock_file.assert_called_once_with(test_filename, 'w') mock_file().write.assert_called_once_with('{"key": "value", "num": 123}') def test_write_json_failure(self): test_data = {"key": "value"} test_filename = "test.json" # 模拟json.dumps抛出异常 with patch("json.dumps") as mock_dumps: mock_dumps.side_effect = TypeError("无法序列化的数据") writer = JsonWriter() result, error = writer.write_json(test_data, test_filename) # 验证返回值正确 self.assertEqual(result, False) self.assertEqual(str(error), "无法序列化的数据")
方案2:使用临时文件,测试实际写入效果
这个方法更贴近真实场景,验证文件是否真的被正确写入了预期内容。可以用tempfile模块创建临时文件,避免污染本地文件系统:
import unittest import json import tempfile import os from your_module import JsonWriter # 替换成你的实际模块名 class TestJsonWriter(unittest.TestCase): def test_write_json_actual_file(self): test_data = {"name": "test", "weights": [0.1, 0.2, 0.3]} # 创建临时文件,关闭后暂不删除,后续手动清理 with tempfile.NamedTemporaryFile(mode='w', delete=False) as temp_file: test_filename = temp_file.name try: writer = JsonWriter() result, error = writer.write_json(test_data, test_filename) # 验证返回值 self.assertEqual(result, True) self.assertIsNone(error) # 读取文件内容,验证是否和预期一致 with open(test_filename, 'r') as f: written_data = json.load(f) self.assertEqual(written_data, test_data) # 验证格式化(可选,因为indent=4会生成带格式的JSON) with open(test_filename, 'r') as f: content = f.read() self.assertIn('\n "name": "test"', content) finally: # 手动删除临时文件 os.unlink(test_filename) def test_write_json_permission_error(self): # 模拟无权限的路径(比如系统根目录下的文件,需要权限) test_data = {"key": "value"} test_filename = "/root/forbidden.json" writer = JsonWriter() result, error = writer.write_json(test_data, test_filename) self.assertEqual(result, False) self.assertIsInstance(error, PermissionError)
总结
- 不需要拆分
write_json方法,它的职责很单一:接收数据和文件名,序列化后写入文件,拆分反而会增加复杂度。 - 优先用方案1做单元测试(快速、无副作用),方案2做集成测试(验证真实行为),两者结合覆盖所有场景。
内容的提问来源于stack exchange,提问作者dean89
相关产品推荐
相关产品推荐

