我正在为Python代码编写测试,这些代码将使用AIOHTTP启动服务器和生产者。尽管服务器必须在后台运行,但是此生产者将在初始化服务器时执行一些异步任务。 我正在使用Asyncio,但我对此很陌生。 我想提供一个正常关机,如指示here。我想测试一下,当收到Ctrl-C(KeyboardInterrupt)时,将有效地触发异常处理以停止并关闭循环和任务。
主要功能的代码如下所示:
def main(foo):
loop = asyncio.get_event_loop()
prod = Producer()
try:
asyncio.ensure_future(webserver.start())
asyncio.ensure_future(prod.set_producer())
loop.run_forever()
except Exception as e:
logging.error("Error: %s", str(e))
except KeyboardInterrupt:
logger.info("Canceling pending tasks and stopping the loop")
asyncio.gather(*asyncio.Task.all_tasks()).cancel()
logger.info("Stopping the loop")
loop.stop()
logger.info("Received Ctrl+C")
loop.close()
还有我要编写的测试:
@pytest.mark.asyncio
async def test_main_exception_correcly(event_loop):
with pytest.raises(KeyboardInterrupt) as excinfo:
event_loop.run_until_complete = asynctest.Mock()
main.prod = asynctest.Mock()
main.prod.set_producer = asynctest.CoroutineMock()
main.asyncio.ensure_future = synctest.Mock(side_effect=KeyboardInterrupt())
event_loop.close = asynctest.Mock()
main.main()
event_loop.close.assert_called()
我知道行with pytest.raises(KeyboardInterrupt) as excinfo
可以捕获任何KeyboardInterrupt
,并且我使用asynctest.Mock()和set_producer协程使用asynctest.CoroutineMock()
模拟了所有异步函数。并且在调用ensure_future
时会产生KeyboardInterrupt
的副作用,从而在调用main.main()时进入异常处理。
但是,此测试未能说明未引发异常:
Failed: DID NOT RAISE <class 'KeyboardInterrupt'>
在没有with pytest.raises(KeyboardInterrupt) as excinfo:
的情况下,我还尝试简化了测试,在这种情况下,测试失败并显示:
concurrent.futures._base.CancelledError
我的测试真的错误吗,还是需要更改异常处理方式?
预先感谢