You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python单元测试中如何正确Mock BeautifulSoup4的ResultSet

可行方案说明

你不需要依赖外部HTML文件,也没必要过度MockResultSet——ResultSet本身就是list的子类,存储的元素是BeautifulSoup的Tag对象,你的函数核心逻辑只依赖两个行为:

  1. 入参可迭代
  2. 迭代出的元素支持通过[key]方式取src和alt属性

下面给两种合规的单元测试写法,优先推荐第一种,稳定性最高。


方案1:直接构造最小可用BS4测试对象(推荐)

用BeautifulSoup自带的API构造测试用Tag/ResultSet,行为和真实HTML解析出来的对象完全一致,没有外部IO依赖,运行速度快,完全满足单元测试隔离要求。

from bs4 import BeautifulSoup, ResultSet
import pytest
from your_module import string_operations

def test_prepare_src_and_alt_basic():
    # 初始化空解析器,仅用于生成测试标签,不需要传入完整HTML
    soup = BeautifulSoup("", "html.parser")
    
    # 构造测试用img标签,覆盖正常场景、缺省属性场景
    img_normal = soup.new_tag("img", src="/img/1.jpg", alt="产品图")
    img_no_alt = soup.new_tag("img", src="/img/2.jpg")
    img_no_src = soup.new_tag("img", alt="无效图片")

    # 构造和select()返回类型完全一致的ResultSet对象
    test_input = ResultSet(soup, [img_normal, img_no_alt, img_no_src])
    
    result = string_operations.prepare_src_and_alt(test_input)
    
    # 断言结果,对齐BS4真实属性访问行为:不存在的属性返回空字符串,缺失src时会触发KeyError(和线上逻辑一致)
    assert result["/img/1.jpg"] == "产品图"
    assert result["/img/2.jpg"] == ""
    with pytest.raises(KeyError):
        _ = result["/img/non-exist.jpg"]

如果你觉得构造Tag的写法麻烦,也可以直接把测试用HTML片段写在测试代码里解析,不需要存成外部文件,同样符合隔离要求:

def test_prepare_src_and_alt_with_inline_html():
    # 测试HTML直接写在测试用例中,无外部依赖
    test_html = """
    <img class="full-image" src="string" alt="another_string" />
    <img class="full-image" src="demo.jpg" alt="示例图" />
    """
    soup = BeautifulSoup(test_html, "html.parser")
    result = string_operations.prepare_src_and_alt(soup.select("img.full-image"))
    
    assert result == {
        "string": "another_string",
        "demo.jpg": "示例图"
    }

方案2:Mock入参对象(不推荐)

如果你的测试场景完全不需要依赖BS4的真实行为,也可以直接Mock入参,但要注意必须对齐BS4的属性访问逻辑,否则会出现测试通过、线上报错的问题:

from unittest.mock import Mock
import pytest
from your_module import string_operations

def test_prepare_src_and_alt_with_mock():
    # 构造Mock图片对象,模拟[]取属性的行为
    def make_mock_img(src, alt):
        mock_img = Mock()
        mock_img.__getitem__ = lambda _, k: {"src": src, "alt": alt}[k]
        return mock_img
    
    test_input = [
        make_mock_img("mock1.jpg", "mock图1"),
        make_mock_img("mock2.jpg", "mock图2")
    ]
    # 函数不需要入参严格是ResultSet类型,传入可迭代的mock对象列表即可运行
    result = string_operations.prepare_src_and_alt(test_input)
    
    assert result == {"mock1.jpg": "mock图1", "mock2.jpg": "mock图2"}

不推荐Mock的原因:你的函数和BeautifulSoup逻辑强耦合,Mock出来的对象无法还原真实场景下的边界行为(比如属性缺失时的返回值、特殊字符转义逻辑等),测试参考价值很低。


内容的提问来源于stack exchange,提问作者Dawid1312

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 15:21:22