如何验证类公共方法按指定顺序调用私有方法?
嗨,我来帮你搞定这个验证方法调用顺序的问题!你的核心需求是确认当SomeClass的process方法在_param为ParamsEnum.VALUE_1时,会先调用_do_intermediate_process,再调用_do_process对吧?我们先看看你之前两个方案失败的原因,再给出正确的实现方式。
为什么你的方案没成功?
方案一的问题
你用mock_container存了两个patch后的mock对象,但这个容器本身并没有被实际调用——实际调用的是SomeClass类上被patch的方法,所以mock_container.method_calls自然是空的,它没法自动同步两个独立mock的调用记录。
方案二的问题
你把process方法mock后用副作用保留原逻辑,但class_mock.assert_has_calls检查的是对class_mock自身方法的调用,而实际执行时调用的是类级别的patch方法,不是class_mock实例上的方法,所以这个断言根本没起到验证顺序的作用,不管你写什么顺序都会通过。
正确的测试实现
其实不用搞这么复杂,我们只需要把实例的私有方法替换成一个Mock对象的方法,这样所有调用都会被这个Mock完整记录,包括调用顺序。直接看代码:
from unittest import mock import unittest from your_module import SomeClass, ParamsEnum # 替换成你的实际模块名 class TestSomeClassProcess(unittest.TestCase): def test_process_method_order(self): # 创建实例,指定触发顺序逻辑的参数 instance = SomeClass(ParamsEnum.VALUE_1) # 创建一个Spy Mock,用来跟踪所有方法调用 method_spy = mock.Mock() # 替换实例的私有方法,让它们指向Spy的对应方法 instance._do_intermediate_process = method_spy._do_intermediate_process instance._do_process = method_spy._do_process # 执行要测试的process方法 instance.process() # 验证两个方法都被调用了一次 method_spy._do_intermediate_process.assert_called_once() method_spy._do_process.assert_called_once() # 关键:验证调用顺序——先执行_intermediate,再执行_process method_spy.assert_has_calls([ mock.call._do_intermediate_process(), mock.call._do_process() ], any_order=False) # any_order=False是默认值,显式写出来更清晰
另一种用类patch的写法
如果你习惯用@mock.patch.object装饰器,也可以这样写,核心是利用mock的调用记录来验证顺序:
@mock.patch.object(SomeClass, '_do_process') @mock.patch.object(SomeClass, '_do_intermediate_process') def test_process_order_with_patch(self, mocked_intermediate, mocked_process): instance = SomeClass(ParamsEnum.VALUE_1) instance.process() # 先验证每个方法的调用次数 mocked_intermediate.assert_called_once() mocked_process.assert_called_once() # 验证调用顺序:把两个mock的调用记录合并到临时mock中检查 temp_mock = mock.Mock() temp_mock.attach_mock(mocked_intermediate, '_do_intermediate_process') temp_mock.attach_mock(mocked_process, '_do_process') temp_mock.assert_has_calls([ mock.call._do_intermediate_process(), mock.call._do_process() ])
这个写法里,attach_mock方法会把两个独立的mock的调用记录合并到temp_mock里,这样就能用assert_has_calls准确验证调用顺序了。
内容的提问来源于stack exchange,提问作者NoisyFlasher
相关产品推荐
相关产品推荐

