You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为依赖用户输入的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 00:25:26