-
Notifications
You must be signed in to change notification settings - Fork 116
Dealing with async functions #155
Copy link
Copy link
Open
Description
When there is a async function we want to test
async def frobnicate(arg0):
raise ValueError("Could not do it")
naïvely we may write (spoiler alert this will not work)
assert_that(calling(frobnicate).with_args(5), raises(ValueError))
As a first suggestion it would be nice if the error message could guide me in the right direction like
Expected: Expected a callable raising <class 'ValueError'>
but: Coroutine returned (Did you mean to await the call)
There's a couple of ways of testing this function that does work but they look a bit clunky or have other issues. Does anyone have suggestions on how to better to do this?
a) using run_until_complete
def calling_async(callable: Callable, *, loop: Loop):
def wrapper(*args, **kwargs):
loop.run_until_complete(callable(*args, **kwargs))
return calling(wrapper)
assert_that(calling_async(frobnicate, loop=loop).with_args(5), raises(ValueError)
Looks pretty neat but has the big down side it's not possible to use when the test method itself is async (like when using pytest-async)
b) testing the result function of a future instead
async def resolved(obj):
fut = asyncio.ensure_future(obj)
await asyncio.wait([fut])
return fut
async def test_frobnicate():
future = await resolved(frobnicate(5))
assert_that(calling(future.result), rasise(ValueError))
This is arguably the more sane approach but with the assert line only being calling(future.result) it loses some context.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels