본문으로 바로가기

Python aiohttp Mocking 하는 방법

category Coding/Python 2019. 10. 30. 12:16
반응형

일반적으로 파이썬을 사용하여 request를 보낼 때 requests모듈을 사용한다. 하지만 해당 모듈은 async/await 즉, 비동기에 대해 지원하지 않으므로 비동기 요청을 보내기 위해서는 aiohttp등의 라이브러리를 사용한다. aiohttp를 통해 get메소드로 요청을 보낼 때는 아래와 같은 형태로 사용한다.


async def request_get(url: str, response_type: str = 'json'):
async with ClientSession(headers=headers) as session:
async with session.get(url) as response:
return await response.json()


보통 Mocking할 때 사용하는것이 unittest의 mock이다. unittest는 파이썬 기본 라이브러리이기 때문에 따로 설치해줄 필요가 없이 바로 사용이 가능하지만, 비동기에 대한 Mocking은 따로 지원하지 않는 것 같다. 따라서 다른 라이브러리를 사용해야하는데, 본 포스팅에서는 asynctest라는 라이브러리를 통해 비동기 코드를 Mocking하는 방법에 대해 설명한다. 먼저 아래의 명령어를 통해 설치한다.


pip3 install asynctest


이제 특정 함수를 patch해줘야하는데, 먼저 아래의 구문을 통해 필요한 함수를 임포트한다.


from asynctest import patch, CoroutineMock


(CoroutineMock : async/await구문을 사용하는것은 코루틴을 사용한다는 뜻이므로 코루틴을 위한 Mock객체를 임포트 시켜준 것) 다음으로 일반적인 unittest의 patch처럼 경로를 적어준다.


@patch('aiohttp.ClientSession.get')
async def test_aiohttp_request(request):
pass


위와 같은 형태로 적어준다. 주의할점은 일반적인 patch처럼 우리가 사용하는 함수의 이름(위 예제에서는 request_get)이 아닌 ClientSession의 get을 patch해줘야하는 부분이다. patch를 하면 Mocking된 객체가 함수의 인자로 넘어오기 때문에 테스트 함수에 인자를 추가해줘야 한다. 이제 여기서 return_value를 명시해줘야 하는데, 이는 다음과 같은 형태로 진행한다.


@patch('aiohttp.ClientSession.get')
async def test_aiohttp_request(request):
request.return_value.__aenter__.return_value.json = CoroutineMock(
side_effect=[리턴 값]
)


위 예제에서는 최종적으로 json된 값을 return하므로 위처럼 리턴값을 정해줬다. 또한 함수 내부에서 Context Manager를 사용하므로 __aenter__를 patch 경로에 포함시켜줬다. 실제 테스트를 진행해보면 정상적으로 동작함을 확인할 수 있다.

반응형