单元测试中如何mock Image.open内的requests.get请求?
正确Mock图片请求的方法
你之前的Mock方式无效,是因为Image.open需要的是类文件对象(支持read()等文件操作),而你直接传二进制数据或者只设置json.return_value都没满足这个要求。以下是正确的实现步骤:
核心思路
让Mock的response.raw指向一个包含有效图片二进制数据的类文件对象(比如BytesIO),同时确保requests.get返回的Mock响应能提供这个对象。
具体代码示例
方法1:动态生成测试图片
from unittest.mock import MagicMock, patch from PIL import Image from io import BytesIO import requests def test_open_image_from_url(): # 1. 生成一张测试用的图片二进制流 test_img = Image.new('RGB', (20, 20), color='blue') img_stream = BytesIO() test_img.save(img_stream, format='PNG') img_stream.seek(0) # 重置流的指针到开头 # 2. Mock requests.get的返回响应 mock_response = MagicMock() mock_response.status_code = 200 mock_response.raw = img_stream # 关键:把raw指向类文件对象 # 3. 执行测试 with patch('requests.get', return_value=mock_response): # 调用你的业务代码(这里模拟原代码逻辑) image_link = "https://example.com/test.png" img = Image.open(requests.get(image_link, stream=True).raw) # 验证结果 assert img.size == (20, 20) assert img.mode == 'RGB'
方法2:使用本地测试图片
如果有现成的测试图片文件,可以直接读取其二进制数据包装成流:
from unittest.mock import MagicMock, patch from PIL import Image from io import BytesIO import requests def test_open_image_from_url_with_local_file(): # 1. 读取本地测试图片为二进制流 with open("test_image.png", "rb") as f: img_stream = BytesIO(f.read()) # 2. Mock响应 mock_response = MagicMock() mock_response.status_code = 200 mock_response.raw = img_stream # 3. 执行测试 with patch('requests.get', return_value=mock_response): image_link = "https://example.com/test.png" img = Image.open(requests.get(image_link, stream=True).raw) # 这里可以根据你的测试图片做断言 assert img.format == 'PNG'
关键注意点
- 必须将
mock_response.raw设置为类文件对象(BytesIO是最常用的选择),不能直接传二进制字节串,否则Image.open无法识别。 - 确保
patch的路径正确:如果你的业务代码是在my_module.py中导入并使用requests.get,那么patch的目标应该是'my_module.requests.get',而不是直接'requests.get',否则Mock不会生效。
内容的提问来源于stack exchange,提问作者horytnik
相关产品推荐
相关产品推荐

