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

pytest Mock类失败求助:如何正确mock easysnmp的Session?

问题:pytest Mock easysnmp.Session 未达预期效果

我是pytest新手,尝试mock easysnmp的Session类但没达到预期效果。下面是业务代码和测试代码,测试中mock Session和walk方法失败,但之前用类似方法处理requests模块的get/post请求是正常的,求帮忙解决。


业务代码(testSnmp.py)

from easysnmp import Session

class testSnmp:  # pylint: disable=too-few-public-methods
    """
    class test snmp conifg
    """

    def __init__(self, hostname="", **params):
        
        self.hostname = hostname
        self.session = Session(
                hostname=self.hostname,
                version=3,
                security_level="auth_with_privacy",
                security_username=params["snmp_username"],
                auth_protocol="SHA",
                auth_password=params["snmp_auth_pwd"],
                privacy_protocol="AES",
                privacy_password=params["snmp_priv_pwd"],
            )


    def run_snmp_check(self):
        """
        snmp run snmp method
        """
        result = {}
        result["hostname"] = self.hostname
        try:
            data = self.session.walk("1.6.6.1.2.1.1.6")
            return self.process_data(data)
        except Exception:
            result["output"] = "Login Failed"
            return result
    
    def process_data(self, data=None):
        result = {}
        result["output"] = []
        if data:
                if data[0].value == "test":
                    res = "login succeeded"
                else:
                    res = "Login Failed"
                result["hostname"] = self.hostname
                result["output"] = res
        return result

原测试代码

import pytest
from unittest.mock import Mock, patch, call
import testSnmp
from easysnmp import Session


@mock.patch('test.Session.walk')
@mock.patch('test.Session')
def test_run_snmp_check(mock_walk, mock_sess):
    params = {"snmp_username":"b", "snmp_auth_pwd":"c", "snmp_priv_pwd":"d"}
    snmp = testSnmp("id_device", **params)
    val = [{"id_device":"test"}]
    mock_sess_response = Mock()
    mock_sess_response.return_value = val
    #mock_sess.assert_called_with()
    resp = snmp.run_snmp_check()
    print(resp)
    
    assert resp == [{"id_device":"test"}]

问题分析与修复

你的测试存在3个核心问题,导致Mock失效:

1. Mock路径错误

业务代码中Session是从easysnmp导入后直接使用的,所以必须Mock业务模块中的Session引用(即testSnmp.Session),而非test.Session。同时你搞反了装饰器顺序:装饰器从下往上生效,最靠近函数的装饰器对应第一个参数,原代码中mock_walk和mock_sess的对应关系完全颠倒。

2. Mock返回值结构不匹配

process_data中需要访问data[0].value,但你返回的是字典,没有value属性,导致逻辑走分支错误。

3. Mock层级错误

需要先让Session类Mock返回一个实例对象,再给这个实例的walk方法设置返回值,而非直接给Session类设置返回值。


修复后的测试代码

import pytest
from unittest.mock import Mock, patch
from testSnmp import testSnmp


@patch('testSnmp.Session')  # 正确Mock业务模块中的Session引用
def test_run_snmp_check(mock_sess):
    # 构建Session实例的Mock对象
    mock_session_instance = Mock()
    mock_sess.return_value = mock_session_instance
    
    # 构建符合process_data预期的walk返回值:带value属性的Mock对象
    mock_snmp_entry = Mock()
    mock_snmp_entry.value = "test"
    mock_session_instance.walk.return_value = [mock_snmp_entry]
    
    # 初始化测试对象
    params = {"snmp_username":"b", "snmp_auth_pwd":"c", "snmp_priv_pwd":"d"}
    snmp = testSnmp("id_device", **params)
    
    # 执行测试方法
    resp = snmp.run_snmp_check()
    
    # 验证结果
    assert resp == {"hostname": "id_device", "output": "login succeeded"}
    
    # 验证Session初始化参数是否正确
    mock_sess.assert_called_once_with(
        hostname="id_device",
        version=3,
        security_level="auth_with_privacy",
        security_username="b",
        auth_protocol="SHA",
        auth_password="c",
        privacy_protocol="AES",
        privacy_password="d"
    )
    
    # 验证walk方法是否被正确调用
    mock_session_instance.walk.assert_called_once_with("1.6.6.1.2.1.1.6")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 06:05:27