测试异常是否停止异步循环

时间:2019-05-23 17:01:38

标签: python pytest python-asyncio

我正在为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

我的测试真的错误吗,还是需要更改异常处理方式?

预先感谢

0 个答案:

没有答案