异步协程的单元测试

时间:2020-04-08 13:01:54

标签: python unit-testing python-asyncio

我想使用nosetests在类中测试协程。我的第一个想法是用asyncio.run()来调用每个协程。不幸的是,在第一次测试后,我开始收到运行时异常。这是显示问题的最小示例:

import asyncio

class MyClass:

    def __init__(self):
        self.event = asyncio.Event()

    async def hello(self):
        print("Hello from MyClass")

class TestMyClass:

    def setup(self):
        self.my_class = MyClass()

    def test1(self):
        asyncio.run(self.my_class.hello())

    def test2(self):
        asyncio.run(self.my_class.hello())

当此脚本与nosetests运行时,将为RuntimeError: There is no current event loop in thread 'MainThread'.引发test2。令人反感的是在Event中创建MyClass。我不太了解这个问题。 documentation for asyncio.run()声明该函数“应被用作异步程序的主要入口,理想情况下应仅被调用一次。”对我来说,这听起来好像可以在程序中多次调用asyncio.run(),即使不建议这样做。

无论如何,由于错误指向不存在的事件循环,我决定手动管理事件循环,并提出以下解决方法:

import asyncio

class MyClass:

    def __init__(self):
        self.event = asyncio.Event()

    async def hello(self):
        print("Hello from MyClass")

class TestMyClass:

    def __init__(self):
        try:
            self.loop = asyncio.get_event_loop()
        except RuntimeError:
            self.loop = asyncio.new_event_loop()

    def setup(self):
        asyncio.set_event_loop(self.loop)
        self.my_class = MyClass()

    def test1(self):
        asyncio.run(self.my_class.hello())

    def test2(self):
        asyncio.run(self.my_class.hello())

依次运行多个测试脚本时,需要初始化中的try...except。我正在使用Python 3.7.6。

我的解决方法对我来说不是很干净,我想知道是否有更好的方法。

1 个答案:

答案 0 :(得分:0)

一个潜在的更清洁的解决方法,因为我仍然使用asyncio低级API,可能是这样的:

import asyncio

class MyClass:

    def __init__(self):
        self.event = asyncio.Event()

    async def hello(self):
        print("Hello from MyClass")

class TestMyClass:

    def __init__(self):
        self.loop = asyncio.get_event_loop()

    def setup(self):
        self.my_class = MyClass()

    def test1(self):
        self.loop.run_until_complete(self.my_class.hello())

    def test2(self):
        self.loop.run_until_complete(self.my_class.hello())

这种方法是否可能存在问题?