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
相关产品推荐
相关产品推荐

