Исправление асинхронного объекта в Python 3.8

#python #async-await #pytest #python-asyncio #python-3.8

#python #асинхронное ожидание #pytest #python-asyncio #python-3.8

Вопрос:

У меня есть вопрос новичка о макетном исправлении асинхронного объекта с помощью Python 3.8. Все, что я пытаюсь, это макет post(), чтобы я мог протестировать логику обработки ошибок, но пока мне не повезло. Не могли бы вы сказать мне, что я сделал не так? Большое спасибо.

main.py

 import httpx


test_data = {"id": "123"}

class DebugClass:
    def post(self):
        try:
            async with httpx.AsyncClient() as client:
                res = await client.post(url='http://localhost:8080', data=test_data)
            return "OK"
        except Exception as e:
            return "NOK"
  

test_main.py

 from unittest import mock
from unittest.mock import patch, AsyncMock


from main import DebugClass

class TestClass:
    @mock.patch('httpx.AsyncClient.post', new_callable=AsyncMock)
    def test_post(self, mock_client_post):
        mock_client_post = AsyncMock(side_effect=TimeoutError)
        debug_class = DebugClass()
        res = debug_class.post()
        assert res == "NOK"
  

Ответ №1:

Для тестирования asyncio кода с помощью pytest я бы посоветовал вам использовать библиотеки pytest-asyncio и asynctest.

Для установки: pip install pytest-asyncio asynctest .

Ниже приведен пример, основанный на вашем коде:

 import httpx
import asynctest
import pytest


class DebugClass:
    async def post(self):
        try:
            async with httpx.AsyncClient() as client:
                res = await client.post(url='http://localhost:8080', data=test_data)
            return "OK"
        except Exception as e:
            return "NOK"


@pytest.mark.asyncio
async def test_debug_class_post():
    with asynctest.patch('httpx.AsyncClient.post') as post_mock:
        post_mock.side_effect = TimeoutError
        debug_class = DebugClass()
        res = await debug_class.post()
        assert res == "NOK"
  

Комментарии:

1. Большое спасибо за вашу помощь, Алекс! Это работает :)! У меня просто есть еще один вопрос. Когда я запускаю ваш код, pytest вернул это предупреждение: Предупреждение об устаревании: декоратор «@coroutine» устарел с Python 3.8, используйте «async def» вместо def wait(self, skip = 0): Просто из любопытства, есть ли какой-либо альтернативный синтаксис для pytest.mark.asyncio? Спасибо 🙂

2. К сожалению, на сегодняшний asyntest день он еще не обновлен для поддержки нового синтаксиса, поэтому я могу только посоветовать вам отключить предупреждение об устаревании

3. Отмечено. Спасибо, Алекс.