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

如何Mock Python-On-Whales的docker.ps实现容器运行状态单元测试?

正确Mock Python-On-Whales docker.ps 的单元测试方案

首先明确问题核心:Python-On-Whales 的 docker.ps() 返回的是Container对象列表,如果Mock时返回None或非可迭代对象,会直接触发"对象不可迭代"错误;若返回值不符合脚本逻辑预期,会导致断言失败(比如返回None而非True)。

第一步:先明确目标脚本(check_container.py)的典型结构

假设你的脚本逻辑大致如下(如果和实际不符,可对应调整测试逻辑):

# check_container.py
from python_on_whales import docker

def is_container_running(container_name: str) -> bool:
    # 通过filters筛选运行中的目标容器
    running_containers = docker.ps(filters={"name": container_name, "status": "running"})
    # 存在匹配容器则返回True,否则False
    return len(running_containers) > 0

第二步:正确的单元测试写法(基于unittest.mock)

测试场景1:容器处于运行状态

from unittest.mock import patch, MagicMock
import check_container

def test_is_container_running_success():
    # 模拟一个符合条件的Container对象(仅需脚本用到的属性,这里是name)
    mock_container = MagicMock()
    mock_container.name = "test-mysql"

    with patch('check_container.docker.ps') as mock_ps:
        # 让Mock的ps方法返回包含该容器的列表
        mock_ps.return_value = [mock_container]
        # 执行测试
        result = check_container.is_container_running("test-mysql")
        # 断言结果正确
        assert result is True
        # 验证ps方法被正确调用(参数匹配)
        mock_ps.assert_called_once_with(filters={"name": "test-mysql", "status": "running"})

测试场景2:容器未运行(或不存在)

def test_is_container_running_failure():
    with patch('check_container.docker.ps') as mock_ps:
        # 让Mock的ps方法返回空列表,表示无匹配容器
        mock_ps.return_value = []
        result = check_container.is_container_running("test-mysql")
        assert result is False
        mock_ps.assert_called_once_with(filters={"name": "test-mysql", "status": "running"})

关键注意事项

  1. Mock路径必须准确:
    必须Mock脚本中实际导入的docker对象的ps方法。比如你的脚本是from python_on_whales import docker,则要Mockcheck_container.docker.ps,而非python_on_whales.docker.ps——这是Mock最常见的错误点。

  2. 返回值必须是可迭代的列表:
    无论测试成功还是失败场景,Mock的ps方法都要返回列表(空或非空),绝对不能返回None或单个对象,否则脚本中len(running_containers)或遍历操作会直接报错。

  3. 按需模拟Container对象属性:
    如果你的脚本中除了检查列表长度,还会访问容器的其他属性(比如id、status),需要给MagicMock添加对应的属性,比如mock_container.id = "abc123"。

基于pytest-mock的简化写法

如果你用pytest和pytest-mock插件,代码会更简洁:

def test_is_container_running_success_pytest(mocker):
    mock_container = mocker.MagicMock()
    mock_container.name = "test-mysql"
    # 直接用mocker.patch替代with语句
    mock_ps = mocker.patch('check_container.docker.ps')
    mock_ps.return_value = [mock_container]

    assert check_container.is_container_running("test-mysql") is True
    mock_ps.assert_called_once_with(filters={"name": "test-mysql", "status": "running"})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 15:50:28