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

Python Monkey Patch无法撤销,导致单元测试用例相互干扰求助

解决pytest monkeypatch无法撤销修改的问题

问题根源

  1. 手动调用monkeypatch.undo()的误区:pytest的monkeypatch fixture默认会在测试用例执行完毕后自动撤销所有通过它做的修改,手动调用undo()会提前撤销单个修改,反而可能打乱内部的撤销队列,导致后续自动撤销逻辑异常。
  2. 未用monkeypatch管理dependency_overrides:直接修改app.dependency_overrides[check_token]的操作不在monkeypatch的管理范围内,所以即使调用undo()也不会清理这部分内容,残留的修改会影响其他测试用例。

修正方案

方案1:移除手动undo(),用monkeypatch统一管理所有修改

将dependency_overrides的修改也交给monkeypatch处理,这样所有修改都会在测试结束后自动被撤销:

@pytest.mark.asyncio
async def test_my_method(monkeypatch):
    # 用monkeypatch.setitem管理dependency_overrides的赋值
    monkeypatch.setitem(app.dependency_overrides, check_token, override_token_expired)

    async def mock_cosmos_query(*args, **kwargs):   
        return fake_spaces    

    monkeypatch.setattr('app.routers.space.cosmos_query', mock_cosmos_query)    
    response = client.get("/api/spaces/TestSpace",  headers={"authorization": "fake user"}, params={"expand": "false"})

    jsonObj = response.json()
    assert response.status_code == 200
    assert jsonObj['name'] == 'TestSpace'  
    # 移除monkeypatch.undo(),让pytest自动处理撤销

方案2:手动清理dependency_overrides(备选)

如果不想用monkeypatch管理dependency_overrides,可以在测试结束后手动恢复该字典的原始状态:

@pytest.mark.asyncio
async def test_my_method(monkeypatch):
    original_override = app.dependency_overrides.get(check_token)
    app.dependency_overrides[check_token] = override_token_expired

    async def mock_cosmos_query(*args, **kwargs):   
        return fake_spaces    

    monkeypatch.setattr('app.routers.space.cosmos_query', mock_cosmos_query)    
    response = client.get("/api/spaces/TestSpace",  headers={"authorization": "fake user"}, params={"expand": "false"})

    jsonObj = response.json()
    assert response.status_code == 200
    assert jsonObj['name'] == 'TestSpace'  

    # 手动恢复dependency_overrides
    if original_override is None:
        del app.dependency_overrides[check_token]
    else:
        app.dependency_overrides[check_token] = original_override
    # 移除monkeypatch.undo(),让pytest自动处理setattr的撤销

关键注意事项

  • 除非明确需要撤销单个修改且不依赖自动清理,否则不要在测试用例中手动调用monkeypatch.undo()。
  • 所有需要在测试后恢复的全局修改,都应该通过monkeypatch的方法(setattr/setitem/delattr等)来操作,确保它们被纳入自动撤销的管理中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 05:15:35