单元测试Mock lauApiSession API失败,求排查代码问题
单元测试Mock问题:如何避免真实网络连接
我负责的项目规模较大,尝试为lauApiSession编写单元测试,测试代码如下:
import unittest from unittest.mock import patch, MagicMock from alm_commons_utils.mylau.lau_client import lauApiSession class TestlauApiSession(unittest.TestCase): @patch("alm_commons_utils.mylau.lau_client.lauApiSession.get_component") def test_mock_get_component(self, mock_get_component): # Mock the return value of get_component mock_get_component.return_value = {"component": "mock_component"} # Initialize the lauApiSession session = lauApiSession( ldap_user="mock_user", ldap_password="mock_password", lau_api_url="https://mock-lau-api-url", lau_login_url="https://mock-lau-login-url" ) # Call the mocked method result = session.get_component("mock_repo") # Assert the mocked method was called with the correct arguments mock_get_component.assert_called_once_with("mock_repo") # Assert the return value is as expected self.assertEqual(result, {"component": "mock_component"}) if __name__ == "__main__": unittest.main()
在GitHub Action中执行该测试任务时,出现以下错误日志:
Run python -m unittest "alm_commons_utils.lautest.mock_lau_client" 2025-06-03 10:58:33,011 - asyncio - DEBUG - Using selector: EpollSelector 2025-06-03 10:58:33,012 [INFO] Retrieving token from lau API... (alm_commons_utils.mylau.lau_client) 2025-06-03 10:58:33,012 - alm_commons_utils.mylau.lau_client - INFO - Retrieving token from lau API... Error: -03 10:58:33,038 [ERROR] Error retrieving token: Cannot connect to host mock-lau-login-url:443 ssl:False [Name or service not known] (alm_commons_utils.mylau.lau_client) 2025-06-03 10:58:33,012 - root - INFO - Entry login_corporativo() 2025-06-03 10:58:33,012 - root - INFO - Entry on endpoint component_yaml_login_corporativo 2025-06-03 10:58:33,012 - root - DEBUG - Yaml alias is: mock_user 2025-06-03 10:58:33,012 - root - INFO - Exit on endpoint component_yaml_login_corporativo 2025-06-03 10:58:33,019 - root - ERROR - Timeout trying to make login 2025-06-03 10:58:33,022 - root - ERROR - Timeout trying to make login 2025-06-03 10:58:33,038 - alm_commons_utils.mylau.lau_client - ERROR - Error retrieving token: Cannot connect to host mock-lau-login-url:443 ssl:False [Name or service not known]
我希望测试完全Mock相关逻辑,不发起真实网络连接,请问我的代码存在什么问题?
问题分析
你只Mock了get_component方法,但**lauApiSession的初始化方法(__init__)内部会自动执行获取token的网络请求**,这部分逻辑没有被Mock,所以初始化session时会尝试连接目标地址,导致报错。
解决方案
需要额外Mock掉初始化时调用的token获取相关逻辑,根据lauApiSession的内部实现,有两种常见处理方式:
方式1:Mock内部的token获取方法
如果lauApiSession内部有专门处理token请求的方法(比如_get_token),直接Mock该方法返回假token:
import unittest from unittest.mock import patch, MagicMock from alm_commons_utils.mylau.lau_client import lauApiSession class TestlauApiSession(unittest.TestCase): # 同时Mock get_component 和 内部token获取方法 @patch("alm_commons_utils.mylau.lau_client.lauApiSession._get_token") @patch("alm_commons_utils.mylau.lau_client.lauApiSession.get_component") def test_mock_get_component(self, mock_get_component, mock_get_token): # Mock token返回值 mock_get_token.return_value = "fake_auth_token" # Mock get_component返回值 mock_get_component.return_value = {"component": "mock_component"} # 初始化session时,_get_token已被Mock,不会发起真实请求 session = lauApiSession( ldap_user="mock_user", ldap_password="mock_password", lau_api_url="https://mock-lau-api-url", lau_login_url="https://mock-lau-login-url" ) result = session.get_component("mock_repo") mock_get_component.assert_called_once_with("mock_repo") self.assertEqual(result, {"component": "mock_component"}) if __name__ == "__main__": unittest.main()
方式2:Mock底层请求库
如果lauApiSession是通过第三方请求库(比如requests)发起token请求,直接Mock对应的请求方法:
import unittest from unittest.mock import patch, MagicMock from alm_commons_utils.mylau.lau_client import lauApiSession class TestlauApiSession(unittest.TestCase): # Mock requests.post和get_component方法 @patch("alm_commons_utils.mylau.lau_client.requests.post") @patch("alm_commons_utils.mylau.lau_client.lauApiSession.get_component") def test_mock_get_component(self, mock_get_component, mock_post): # 构造Mock响应对象 mock_response = MagicMock() mock_response.json.return_value = {"token": "fake_auth_token"} mock_response.status_code = 200 mock_post.return_value = mock_response # Mock get_component返回值 mock_get_component.return_value = {"component": "mock_component"} # 初始化session,不会触发真实请求 session = lauApiSession( ldap_user="mock_user", ldap_password="mock_password", lau_api_url="https://mock-lau-api-url", lau_login_url="https://mock-lau-login-url" ) result = session.get_component("mock_repo") mock_get_component.assert_called_once_with("mock_repo") self.assertEqual(result, {"component": "mock_component"}) if __name__ == "__main__": unittest.main()
核心思路是找到lauApiSession初始化时触发网络请求的根源,把对应的依赖Mock掉,确保整个测试流程没有真实的网络调用。
内容的提问来源于stack exchange,提问作者MJoao
相关产品推荐
相关产品推荐

