如何在Python Unittest中根据输入断言另一个类的方法被调用
问题分析与解决方案
原代码的核心问题
- 输入类型不匹配:
input()返回的是字符串类型,原代码直接和整数1比较,条件永远不成立,导致datamanager.import_from_file()永远不会被执行。 - Mock对象错误:测试代码给
self.test_interface添加了import_from_file的Mock,但原Interface类的user_interface方法调用的是全局datamanager实例的方法,不是自身方法,Mock对象完全没起作用。
修正后的测试代码
方案1:调整业务代码的输入判断
先修改Interface类的user_interface方法,将输入转为整数:
class Interface: def user_interface(self): my_val = int(input()) # 转为整数匹配判断条件 if my_val == 1: datamanager.import_from_file()
然后编写正确的测试代码:
import unittest from unittest.mock import patch from your_module import Interface, datamanager # 替换为你的实际模块名 class TestInterface(unittest.TestCase): def setUp(self): self.test_interface = Interface() def tearDown(self): print("End Test\n") @patch('builtins.input', side_effect=[1]) @patch('your_module.datamanager') # Mock全局的datamanager实例 def test_user_interface_calls_import(self, mock_datamanager, mock_input): self.test_interface.user_interface() # 断言目标方法被调用一次 mock_datamanager.import_from_file.assert_called_once() if __name__ == '__main__': unittest.main()
方案2:不修改业务代码,模拟字符串输入
如果不想改动业务代码,只需把模拟输入改为字符串"1":
import unittest from unittest.mock import patch from your_module import Interface, datamanager class TestInterface(unittest.TestCase): def setUp(self): self.test_interface = Interface() def tearDown(self): print("End Test\n") @patch('builtins.input', side_effect=["1"]) # 模拟字符串输入匹配原判断逻辑 @patch('your_module.datamanager') def test_user_interface_calls_import(self, mock_datamanager, mock_input): self.test_interface.user_interface() mock_datamanager.import_from_file.assert_called_once() if __name__ == '__main__': unittest.main()
关键说明
- Mock目标正确:必须Mock
Interface类实际引用的全局datamanager实例,通过@patch('your_module.datamanager')实现(替换your_module为实际模块文件名)。 - 输入类型匹配:确保模拟输入和业务代码的判断条件类型一致,要么业务代码转整数,要么测试传字符串
"1"。 - Mock时机:在调用
user_interface前完成Mock,保证方法执行时使用Mock对象。
内容的提问来源于stack exchange,提问作者SuperDieter
相关产品推荐
相关产品推荐

