I am new with asyncio. I am using aiohttp and aiofiles for downloading images. how to write the unit tests for both of these.
class ImageDownloader:
def __init__(self, folder_path: str):
self.folder_path = folder_path
async def async_download_image(self, image_name: str, image_url: str):
logging.info("%s downloading is started", image_name)
async with aiohttp.ClientSession() as session:
async with session.get(image_url) as resp:
if resp.status == 200:
logging.info(" %s downloading is finished", image_name)
image_saving_path = os.path.join(self.folder_path, image_name)
logging.info(" %s saving to directory is started", image_name)
file = await aiofiles.open(image_saving_path, mode='wb')
await file.write(await resp.read())
await file.close()
logging.info(" %s saving to directory is finished", image_name)
else:
logging.exception(IMAGE_DOWNLOADER_EXCEPTION + image_name)
raise ImageDownloaderError(IMAGE_DOWNLOADER_EXCEPTION + image_name)
Since Python 3.8 there is
unittest.IsolatedAsyncioTestCasewhich let's you test your write unittest for any asyncio code conveniently:Regarding
aiohttpit is officially recommended (see warning in the docs "Faking request object") to run a local server to test your client. To be honest, I have no clue why, as it disagrees with the standard rule to mock expensive dependencies. Anyway, to do so you have to redesign your function so it's accepting the session object as a parameter. This way, you can redirect the requests with the help of a mocked resolver to your local test server.It may be easier to bypass the whole
aiohttplib completely by mocking the session object itself and yielding prepare handcrafted test responses.I have no idea about
aiofilesbut the same pattern holds for file input/output as well. Pass in a mocked file_like. which preferably holds everything in memory.