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

Python单元测试读取标准输入模块时第二个测试输出为空问题

问题原因

核心问题是模块顶层代码只会在第一次导入时执行。第一次测试用例运行时,导入main模块,模块内的print(len(input()) + ...)会立即执行,此时mock的输入生效,输出正常。但第二个测试用例执行时,Python已将main模块缓存到sys.modules中,即便尝试卸载模块,只要测试代码中仍存在对main的引用,缓存就无法彻底清除,模块顶层代码不会再次执行,因此没有输出。

解决方法

1. 重构main.py,将逻辑封装为函数(推荐)

把原顶层代码放到函数里,避免依赖模块导入时机,测试时可主动调用:

# main.py
def check_total_length():
    total = len(input()) + len(input()) + len(input())
    print(total == 10)

if __name__ == "__main__":
    check_total_length()

对应的测试用例调整为:

import unittest
from unittest.mock import patch
import main

class TestMain(unittest.TestCase):
    def test_total_length_equal_10(self):
        with patch('builtins.input', side_effect=["a", "abcdefgh", "I"]):
            with patch('builtins.print') as mock_print:
                main.check_total_length()
                mock_print.assert_called_once_with(True)
    
    def test_total_length_not_equal_10(self):
        with patch('builtins.input', side_effect=["a", "b", "c"]):
            with patch('builtins.print') as mock_print:
                main.check_total_length()
                mock_print.assert_called_once_with(False)

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

2. 若必须保留原main.py结构

可在每个测试用例前强制重新加载模块:

import unittest
from unittest.mock import patch
import sys
import importlib

class TestMain(unittest.TestCase):
    def setUp(self):
        # 每次测试前移除模块缓存并重新导入
        if 'main' in sys.modules:
            del sys.modules['main']
        self.main_module = importlib.import_module('main')
    
    def test_total_length_equal_10(self):
        with patch('builtins.input', side_effect=["a", "abcdefgh", "I"]):
            with patch('builtins.print') as mock_print:
                importlib.reload(self.main_module)
                mock_print.assert_called_once_with(True)
    
    def test_total_length_not_equal_10(self):
        with patch('builtins.input', side_effect=["a", "b", "c"]):
            with patch('builtins.print') as mock_print:
                importlib.reload(self.main_module)
                mock_print.assert_called_once_with(False)

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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 14:54:55