如何Mock Python类__init__方法中的self.project变量用于测试?
解决方案
你之前的做法错误在于直接patch类的project属性——self.project是实例属性,在类初始化时赋值,patch类属性无法覆盖实例已创建的属性,且无法拦截__init__中实际调用的gitlab相关方法。下面提供两种可行的Mock方案:
方案一:Patch Gitlab依赖链,模拟完整调用流程
通过patchgitlab.Gitlab,拦截所有与Gitlab的交互,直接返回Mock对象:
from unittest.mock import patch, MagicMock from src.get_merge_request_info import GetMRsInfo @patch('gitlab.Gitlab') def test_get_merge_request_state(mock_gitlab): # 配置Gitlab实例的Mock mock_git_instance = mock_gitlab.return_value mock_project = MagicMock() # 让projects.get返回Mock的project对象 mock_git_instance.projects.get.return_value = mock_project # 配置merge request的Mock返回值 mock_mr = MagicMock() mock_mr.state = 'opened' mock_project.mergerequests.get.return_value = mock_mr # 创建类实例(此时所有gitlab调用都是Mock的) git = GetMRsInfo( gitlab_endpoint="https://example.gitlab.com", private_token="ASD123", project_name_with_namespace="test/example/com" ) # 调用方法并验证结果 merge_request_state = git.get_merge_request_state(123) assert merge_request_state == 'opened'
方案二:直接替换实例的self.project属性
先创建实例(需临时patch Gitlab避免实际网络请求),再直接替换实例的project属性为Mock对象:
from unittest.mock import patch, MagicMock from src.get_merge_request_info import GetMRsInfo def test_get_merge_request_state_direct_replace(): # 临时patch Gitlab,避免初始化时发起实际请求 with patch('gitlab.Gitlab'): git = GetMRsInfo( gitlab_endpoint="https://example.gitlab.com", private_token="ASD123", project_name_with_namespace="test/example/com" ) # 替换实例的project属性为Mock对象 mock_project = MagicMock() mock_mr = MagicMock() mock_mr.state = 'opened' mock_project.mergerequests.get.return_value = mock_mr git.project = mock_project # 调用方法并验证结果 merge_request_state = git.get_merge_request_state(123) assert merge_request_state == 'opened'
方案对比
- 方案一适合需要验证
__init__中Gitlab调用逻辑的场景,完全隔离外部依赖; - 方案二更轻量化,适合仅测试
get_merge_request_state方法逻辑的场景。
内容的提问来源于stack exchange,提问作者Sergey Turivniy
相关产品推荐
相关产品推荐

