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

如何用pytest为含多轮循环(如带退出条件的while True)的函数Mock输入?

解决多次input调用的monkeypatch模拟问题

你的问题出在两个核心点:

  • 多次调用monkeypatch.setattr("builtins.input")会直接覆盖前一次的设置,所以最后只有返回"Exit"的lambda生效,根本不会用到input_user的值。
  • 你在调用main()之后才设置sys.stdout的mock,这时候main()的输出已经打印到真实控制台了,fake_output根本捕获不到内容。

正确的实现方式

要模拟连续多次的input()调用,你可以用迭代器来提供按顺序的输入值,让每次input()调用依次取出迭代器里的元素。同时要先设置好stdout的mock,再执行main()。

修改后的测试代码如下:

from io import StringIO

def test_main_scenario(input_user, expected, monkeypatch):
    # 用迭代器提供连续输入:先返回input_user,再返回"Exit"
    inputs = iter([input_user, "Exit"])
    monkeypatch.setattr("builtins.input", lambda _: next(inputs))
    
    # 先捕获stdout,再执行main
    fake_output = StringIO()
    monkeypatch.setattr("sys.stdout", fake_output)
    
    main()
    
    # 获取捕获的输出并断言
    output = fake_output.getvalue()
    assert output == expected

代码解释

  1. 迭代器模拟连续输入:iter([input_user, "Exit"])创建一个迭代器,每次调用next(inputs)会依次取出列表里的元素。把这个逻辑传给builtins.input,就能让main()里第一次input()拿到input_user,第二次拿到"Exit",从而触发循环退出。
  2. 提前设置stdout mock:在调用main()之前就把sys.stdout替换成StringIO实例,这样main()里所有的print内容都会被写入到fake_output里,后续就能正确获取并断言。

如果需要模拟更多次输入,只需要在迭代器的列表里添加对应的值即可,比如iter(["first", "second", "Exit"])就能模拟三次输入。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 20:24:51