pytest异步单元测试出现Never awaited警告及StopAsyncIteration错误
问题解决方法
问题根源
你遇到的警告和报错本质是代码逻辑冗余导致的:
- 你手动调用两次
get_sugar_api_records的操作完全多余:你的测试目标是验证get_calls主函数的逻辑,该函数内部本来就会触发两次get_sugar_api_records调用,不需要你提前手动触发。 - 没有加
await时,异步函数的协程对象没有被执行,不会消费AsyncMock配置的side_effect返回值,但会触发协程未等待的运行时警告。 - 加上
await后,两次手动调用会把side_effect列表里的两个返回值全部消费,后续get_calls执行时再次调用get_sugar_api_records就没有可返回的内容,自然抛出StopAsyncIteration错误。
解决步骤
- 删掉你手动调用
get_sugar_api_records的两行代码 - 把原本放在调用前的传参断言,移到
get_calls执行完成之后,此时AsyncMock的调用记录已经完整生成,可以直接校验传参是否符合预期。
修改后的完整代码
@pytest.mark.asyncio async def test_get_score_calls(monkeypatch, set_env_var): m = mock.AsyncMock() m.side_effect = [ await get_sugar_api_records_for_calls_main(url, access_token, payload), await get_sugar_api_records_for_calls_sub(url, access_token) ] monkeypatch.setattr(calls, 'get_sugar_api_records', m) ##-# mocking the "scevents_time" function mock_scevents_time = mock.MagicMock(name = 'Mock Method: mock_scevents_time') mock_scevents_time.return_value = scevents_time_return_value_valid monkeypatch.setattr(calls, 'scevents_time', mock_scevents_time) ##-# mocking get_none_overlapping_duration funtion mock_get_none_overlapping_duration = mock.MagicMock(name = 'Mock Method: mock_get_none_overlapping_duration') mock_get_none_overlapping_duration.return_value = 15 monkeypatch.setattr(calls, 'get_none_overlapping_duration', mock_get_none_overlapping_duration) # 先执行主函数 assert await calls.get_calls('1', '2021-9-9', [[0, 0], [23, 59]], -7.0, 'sugar.domain.org', access_token) == expected_result_call_score # 再校验异步方法的调用传参 assert m.call_args_list[0] == mock.call(url, access_token, payload) assert m.call_args_list[1] == mock.call(url, access_token)
内容的提问来源于stack exchange,提问作者Anuruddha Bandara
相关产品推荐
相关产品推荐

