如何Mock Django ViewFlow中的Handler方法?
解决ViewFlow中Flow方法Mock失败的问题
问题原因
ViewFlow在Django启动时会自动实例化Flow类,而你的do_stuff = flow.Handler(this.do_stuff_handler)代码会在类实例化阶段就绑定了do_stuff_handler的实例方法引用。后续你patch类上的do_stuff_handler时,已经初始化的Handler对象引用的还是原来的绑定方法,所以Mock不会生效。
解决思路及代码示例
1. 直接Patch已实例化Flow对象的Handler引用
ViewFlow通常会把Flow类维护为单例(比如通过MyFlow.instance访问),直接找到这个实例的Handler对象,替换它的回调引用:
from unittest import mock from django.test import TestCase from app1.flows import MyFlow class MyFlowTest(TestCase): def test_do_stuff_handler_called(self): # 获取已实例化的Flow对象,替换其Handler的handler属性 with mock.patch.object(MyFlow.instance.do_stuff, 'handler') as mock_handler: # 执行触发流程的代码,比如启动流程并走到do_stuff节点 flow_instance = MyFlow.instance.start.run() flow_instance.do_stuff.run() # 断言mock被调用 mock_handler.assert_called_once()
2. 在ViewFlow实例化Flow类前提前Patch
调整测试的导入顺序,确保在ViewFlow加载并实例化MyFlow之前就完成方法Patch:
from unittest import mock # 先Patch类方法,再导入Flow类 mock_do_stuff = mock.patch('app1.flows.MyFlow.do_stuff_handler').start() from django.test import TestCase from app1.flows import MyFlow class MyFlowTest(TestCase): def tearDown(self): # 测试结束后停止所有mock mock.patch.stopall() def test_do_stuff_handler_called(self): # 执行流程操作 flow_instance = MyFlow.instance.start.run() flow_instance.do_stuff.run() mock_do_stuff.assert_called_once()
3. Patch ViewFlow Handler的执行逻辑
如果前两种方法不适用,可以直接Mock Handler的执行方法,通过断言执行参数来验证目标方法是否被触发:
from unittest import mock from django.test import TestCase from app1.flows import MyFlow class MyFlowTest(TestCase): @mock.patch('viewflow.flow.Handler.execute') def test_do_stuff_handler_called(self, mock_execute): # 执行流程操作 flow_instance = MyFlow.instance.start.run() flow_instance.do_stuff.run() # 断言Handler的execute方法被调用,且传入的handler是目标方法 mock_execute.assert_called() call_args = mock_execute.call_args[0] self.assertEqual(call_args[0].handler, MyFlow.do_stuff_handler)
内容的提问来源于stack exchange,提问作者James Lin
相关产品推荐
相关产品推荐

