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

Python单元测试:如何测试被其他函数调用的依赖函数

withdraw_cash 函数单元测试实现方案

是否需要使用mock/patch?

必须用。单元测试的核心是隔离被测逻辑,你不需要走bank_atm的完整调用链路,直接单独测试withdraw_cash即可。这个函数存在两个必须隔离的外部依赖,必须靠patch工具模拟才能完成自动化测试:

  • 依赖1:内置input()控制台输入函数,真实调用会阻塞等待人工输入,无法自动化执行,需要模拟返回不同输入值覆盖各类场景
  • 依赖2:全局user字典,测试过程中会修改余额字段,必须在每个用例执行前重置初始值,避免用例之间互相污染结果

测试覆盖场景实现

你可以用Python自带的unittest框架+unittest.mock.patch完成测试,两个校验场景的实现逻辑如下:

场景1:校验取款金额输入合法性

  • 模拟input()第一次返回非数字内容(比如"abc"),第二次返回合法数字值(避免while无限循环)
  • 验证函数捕获输入转换的ValueError后,正确打印输入错误提示,不会直接崩溃

场景2:校验取款金额不超过账户可用余额

  • 每个用例执行前先把全局user['balance']重置为初始值100
    • 子场景1:模拟输入金额大于余额(比如150),验证函数抛出余额不足的ValueError,余额不会被修改
    • 子场景2:模拟输入金额小于等于余额(比如30),验证函数正常执行,余额扣减正确(剩余70)

可直接运行的测试代码

import unittest
from unittest.mock import patch
import io
import sys
# 从你的业务代码文件中导入withdraw_cash和user,例如业务代码存为atm.py则写为from atm import withdraw_cash, user

class TestWithdrawCash(unittest.TestCase):
    def setUp(self):
        # 每个测试用例执行前重置余额为初始值100
        user['balance'] = 100

    def test_invalid_amount_input(self):
        # 捕获标准输出验证提示打印逻辑
        captured_output = io.StringIO()
        sys.stdout = captured_output
        # 第一次返回非法输入abc,第二次返回合法值20避免无限循环
        with patch('builtins.input', side_effect=['abc', '20']):
            withdraw_cash()
        sys.stdout = sys.__stdout__
        output = captured_output.getvalue()
        # 校验错误提示正常打印
        self.assertIn("Enter correct amount: ", output)
        # 校验合法输入后余额扣减正确
        self.assertEqual(user['balance'], 80)

    def test_amount_exceed_balance(self):
        # 模拟输入150,超过初始余额100
        with patch('builtins.input', return_value='150'):
            with self.assertRaises(ValueError) as context:
                withdraw_cash()
        # 校验错误提示文本正确
        self.assertEqual(str(context.exception), "You don't have sufficient balance to make this withdrawal")
        # 校验余额未被异常修改
        self.assertEqual(user['balance'], 100)

    def test_valid_withdraw(self):
        captured_output = io.StringIO()
        sys.stdout = captured_output
        # 模拟正常取款30
        with patch('builtins.input', return_value='30'):
            withdraw_cash()
        sys.stdout = sys.__stdout__
        output = captured_output.getvalue()
        # 校验剩余余额提示正常打印
        self.assertIn("£70", output)
        # 校验余额扣减结果正确
        self.assertEqual(user['balance'], 70)

if __name__ == '__main__':
    unittest.main()

注意:patch的input路径要和你业务代码的模块名对应,如果业务代码文件名为atm.py,也可以将patch路径写为atm.input,确保patch的是被测模块实际调用的input引用。

内容的提问来源于stack exchange,提问作者Jennifer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 01:09:19