测试else分支中调用的get_sync_column函数断言失败问题排查
问题:Mock断言失败且else分支未覆盖的解决方法
我编写了一段代码,在cal_sync_column方法的else分支中调用返回字符串的get_sync_column函数。对该函数Mock后断言它被调用一次,但断言失败,同时代码覆盖率因else分支里的get_sync_column()未被覆盖而下降。
原函数
from dataclasses import dataclass, ClassVar @dataclass(frozen=True) class RMTable(): sync_column: ClassVar[str] = None def __post_init__(self) -> None: if self.sync_column is None: object.__setattr__(self, "sync_column", self.cal_sync_column()) def cal_sync_column(self) -> str: if not feature_flag(): return "_synced" else: return get_sync_column() # returns str
测试函数
from unittest.mock import patch, MagicMock def test_sync_column(): with patch("my_module.feature_flag") as feature_flag_mock: with patch("my_module.get_sync_column") as mock_sync_column: feature_flag_mock.return_value = True rm_table_mock = MagicMock(spec=RMTable) rm_table_mock.cal_sync_column.return_value = "FLAG_1" result = rm_table_mock.cal_sync_column() assert result == "FLAG_1" mock_sync_column.assert_called_once()
错误信息
AssertionError: Expected 'get_sync_column' to have been called once. Called 0 times.
问题原因
你用MagicMock(spec=RMTable)创建了RMTable的Mock对象,并且直接给rm_table_mock.cal_sync_column.return_value赋值为"FLAG_1"。这导致调用rm_table_mock.cal_sync_column()时,执行的是Mock的预设返回值,完全没有触发真实的cal_sync_column方法逻辑,自然不会走到else分支调用get_sync_column,所以断言失败,同时真实代码的else分支也没被覆盖。
修正方案
要测试真实的cal_sync_column逻辑,应该实例化真实的RMTable对象,仅Mockfeature_flag和get_sync_column这两个外部依赖:
修正后的测试代码
from unittest.mock import patch def test_sync_column(): with patch("my_module.feature_flag") as feature_flag_mock: with patch("my_module.get_sync_column") as mock_sync_column: # 设置feature_flag返回True,触发else分支 feature_flag_mock.return_value = True # 预设get_sync_column的返回值 mock_sync_column.return_value = "FLAG_1" # 实例化真实的RMTable对象 rm_table = RMTable() # 调用真实的cal_sync_column方法 result = rm_table.cal_sync_column() assert result == "FLAG_1" mock_sync_column.assert_called_once()
额外测试__post_init__逻辑
如果要验证__post_init__中自动调用cal_sync_column设置sync_column的逻辑,可以直接实例化对象后断言属性值:
from unittest.mock import patch def test_post_init_sync_column(): with patch("my_module.feature_flag") as feature_flag_mock: with patch("my_module.get_sync_column") as mock_sync_column: feature_flag_mock.return_value = True mock_sync_column.return_value = "FLAG_1" rm_table = RMTable() # 断言sync_column被正确初始化 assert rm_table.sync_column == "FLAG_1" mock_sync_column.assert_called_once()
内容的提问来源于stack exchange,提问作者vaibhav
相关产品推荐
相关产品推荐

