如何为依赖用户输入的ATM存款函数编写单元测试?
为ATM存款操作编写单元测试的解决方案
你的存款函数当前直接依赖用户输入、控制台输出,还使用了递归调用,这些都让单元测试变得困难。要写出可靠的单元测试,首先需要把业务逻辑和外部依赖(输入输出、后续操作)解耦,再针对核心逻辑编写测试用例。
第一步:重构原代码,降低耦合
把输入、输出、后续操作从核心逻辑中分离出来,让函数更易于测试:
def deposit_operation(user, amount=None, print_func=print, next_operation_func=None): # 处理交互式输入(测试时可直接传入amount跳过) if amount is None: amount = int(input('ENTER AMOUNT YOU WANT TO DEPOSIT: ')) # 验证金额有效性:补充负数校验 if amount <= 0: error_msg = 'DEP...' print_func(error_msg) if amount is None: return deposit_operation(user, print_func=print_func, next_operation_func=next_operation_func) return False, error_msg # 验证金额是否为1000的倍数 if amount % 1000 != 0: error_msg = 'AMOUNT YOU WANT TO DEPOSIT MUST BE IN MULTIPLES OF 1000 NAIRA NOTES' print_func(error_msg) if amount is None: return deposit_operation(user, print_func=print_func, next_operation_func=next_operation_func) return False, error_msg # 更新余额核心逻辑 user[4] += amount success_msg = f'*** YOUR NEW BALANCE IS: {user[4]} NAIRA ****' print_func(success_msg) # 执行后续操作(测试时可传入mock替代) if next_operation_func: next_operation_func(user) return True, success_msg
第二步:编写单元测试
用Python标准库的unittest结合Mock来模拟外部依赖,覆盖各种场景:
import unittest from unittest.mock import Mock class TestDepositOperation(unittest.TestCase): def setUp(self): # 初始化测试用户,索引4为当前余额 self.test_user = ['Bocco', '67890', 'current', 'active', 5000] def test_valid_deposit_updates_balance(self): # 测试存入有效金额(2000奈拉) success, msg = deposit_operation( self.test_user, amount=2000, print_func=Mock(), next_operation_func=Mock() ) self.assertTrue(success) self.assertEqual(self.test_user[4], 7000) self.assertEqual(msg, '*** YOUR NEW BALANCE IS: 7000 NAIRA ****') def test_invalid_amount_not_multiple_of_1000(self): # 测试存入非1000倍数的金额 success, msg = deposit_operation( self.test_user, amount=1500, print_func=Mock() ) self.assertFalse(success) self.assertEqual(msg, 'AMOUNT YOU WANT TO DEPOSIT MUST BE IN MULTIPLES OF 1000 NAIRA NOTES') # 余额未变化 self.assertEqual(self.test_user[4], 5000) def test_negative_amount_rejected(self): # 测试存入负数金额 success, msg = deposit_operation( self.test_user, amount=-1000, print_func=Mock() ) self.assertFalse(success) self.assertEqual(msg, 'DEP...') # 对应你补充的负数错误信息 self.assertEqual(self.test_user[4], 5000) if __name__ == '__main__': unittest.main()
测试关键点说明
- Mock外部依赖:用
Mock()替代print和next_operation_func,避免测试时产生实际输出或触发后续操作 - 直接传入测试数据:通过
amount参数直接传入测试用例的金额,不需要依赖用户输入 - 验证核心逻辑:检查余额是否正确更新,返回的状态和消息是否符合预期
- 覆盖边界场景:包括有效金额、无效金额、负数、零等情况,确保函数行为稳定
内容的提问来源于stack exchange,提问作者Bocco Aniefiok
相关产品推荐
相关产品推荐

