🥦
Django-DRFでFileField(ImageField)のユニットテストどうするのか
始めに
Django、DjangoRestFrameworkを使用したAPI開発後、ファイルアップロード(POST, PUT)をどのように実装するのか、以外とハマったので備忘兼共有
※コードベースで行います
環境
django==3.2.x
djangorestframework==3.13.1
ViewでParserを設定
file_upload_api_view.py
class FileUploadAPIView(APIView):
permission_classes = [IsAuthenticated]
parser_classes = [JSONParser]
def get_parsers(self):
"""Parserをメソッド毎等条件で切り替える
PUTのみ[MultipartParser, FormParser]を使用
"""
self.parser_classes = [JSONParser]
if self.request.method.upper() == 'PUT':
self.parser_classes = [MultiPartParser, FormParser]
return super(UserCurrentProfileAPIView, self).get_parsers()
def put(self, request):
"""PUTメソッド"""
user = self.request.user
serializer = FileUploadSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=200, data=serializer.data)
else:
raise ValidationException("適当に例外をraise")
テストコード
test_file_upload_api_view.py
from django.test import TestCase
from django.test.client import MULTIPART_CONTENT, encode_multipart, BOUNDARY
from rest_framework.test import APIClient
class FileUploadAPIViewTest(TestCase):
def test_file_upload(self):
"""ファイルアップロードを検証"""
// 準備(ユーザ等の準備処理は割愛)
api_client = APIClient()
api_client.credentials(HTTP_AUTHORIZATION=f"Token {token}")
// パラメータ準備(parameterはimageとnameのみ)
parameters = {
"name": "file_name",
"image": open((os.path.dirname(os.path.abspath(__file__))) + '/sample.jpg', 'rb')
}
// 実行
response = api_client.put(
path="/api/image/upload/",
data=encode_multipart(data=parameters, boundary=BOUNDARY),
content_type=MULTIPART_CONTENT)
// 検証
self.assertEqual(200, response.status_code)
ひとこと
今回はMultiPartParserを使用したアップロードです。
テストの時に形式関連でエラーが出たりと色々ハマりそうだったので共有です。
実際はファイルをサーバ経由でストレージにアップロードするのも効率が悪いので、直接ストレージにアップロードさせる方が良いと感じてます。(S3署名付きアップロードとか...)
検証内容についてはDB更新されていることの検証等を実行前、実行後に行なったりすると良いと思います。
事前準備は担保されているものとするなら実行後検証のみでOK
さいごに
そういえば今度Djangoのカンファレンスがあるので参加します。一般枠です。
オフラインなので緊張しますが、、、猛者に囲まれて頑張ります。
参考ツイート(今見たら残り1人でした・・・)
Discussion