외부 API가 있는 view를 E2E 테스트를 하고 싶다. 하지만 테스트를 할 때마다 외부 API를 요청하는 건 자원 낭비다.(사실 다른 이유가 있을 순 있는데 내가 생각하기에는) 예를 들어 파일 업로드를 S3에 한다고 치자. 만약 테스트 할 때마다 S3에 업로드한다면 말이 되는가?(사실 내가 했다. 근데 뭔가 이상한 점을 눈치챘으니 봐주자)
이럴 때 Mock을 써보자!
테스트코드
예를 들어보자. 당신은 foo api를 테스트해보고 싶다. foo api는 외부 API를 요청받아 보여준다. 그런데 외부 API는 트래픽 제한이 있다. 100번의 트래픽 제한 중에 50번을 테스트한다고 치면 실제 서비스에서는 50번 밖에 사용자에게 못 보여준다. 어쩔 건가?
아무런 조치를 취하지 않은 API Test
test.py:
class FooAPITests(APITestCase):
def test_foo_api_view(self, mock_get, mock_get2):
url = "/foo/"
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
service.py
def request_external_api():
...
return {...}
views.py
from app.service import request_external_api
def foo_list(request):
...
response = request_external_api() # 최대 100번만 요청할 수 있는 외부 API
return render(request, ..., {
'foo_list': response,
})
이제 Mock을 이용하여 테스트를 진행해 보자. 간단하게 return value만 조작해 보자.
class FooAPITests(APITestCase):
@patch("app.service.request_external_api")
def test_foo_api_view(self, mock_get):
url = "/foo/"
mock_get.return_value = {"test": "mock is success"}
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
이렇게 하고 console에 출력하도록 코드를 수정해 보자.
from app.service import request_external_api
def foo_list(request):
...
response = request_external_api() # 최대 100번만 요청할 수 있는 외부 API
print(response)
return render(request, ..., {
'foo_list': response,
})
이렇게 하고 테스트를 해보면 해당 True로 찍힌 모습을 볼 수 있다.
혹시나 외부 API가 2개라면 다음과 같이 하면 되더라.
class FooAPITests(APITestCase):
@patch("app.service.request_external_api2")
@patch("app.service.request_external_api")
def test_foo_api_view(self, mock_get_api, mock_get_api2):
url = "/foo/"
mock_get.return_value = {"test": "mock is success"}
mock_get_api2.return_value = {"test2": "mock2 is success"}
response = self.client.get(url, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
'Django' 카테고리의 다른 글
DRF - Null인 경우 마지막에 배치하도록 하기 (0) | 2023.04.17 |
---|---|
django-import-export 비동기 활용하기 (0) | 2023.04.13 |
Django Filterset 활용하기 (0) | 2023.03.13 |
Django staticfile 관리하기 (0) | 2023.03.01 |
[DRF] Serializer relations (0) | 2023.02.26 |