Подражание объекту запроса для передачи методу ViewSet create()

Я изучаю unittest и unittest.mock, и борюсь с концепциями и реализациями в основном с mock.

Для контекста, то, с чем я играю, это Django / DRF API и Redis. Я пытаюсь написать тесты, для которых необходимо подружить вызовы Redis.

Вот тест, над которым я работаю:

# tests.py

import unittest
from unittest.mock import patch

from core.views import KeysViewSet


class KeysViewSetTestCase(unittest.TestCase):

    def setUp(self):
        self.json_object = {'key': 'hello', 'value': 'world'}
        self.view = KeysViewSet()

    def test_create(self):
        with patch('core.views.RedisUtil.create') as mocked_create:
            mocked_create.return_value.data = True

            created = self.view.create(self.json_object)

views.py:

# viefws.py

# Third party imports
from rest_framework import status, viewsets
from rest_framework.response import Response

# Croner imports
from .serializers import KeysSerializer

# Import Redis
from .utils import RedisUtil


class KeysViewSet(viewsets.ViewSet):
    """
    METHOD      URI                 DESCRIPTION    
    GET         /api/keys/<:key>/   Returns specific value from key
    POST        /api/keys/          Creates a new key/value
    DELETE      /api/keys/<:key>/   Deletes a specific key
    """

    def __init__(self, *args, **kwargs):
        """
        Instantiate the RedisUtil object.
        """
        self.redis_util = RedisUtil()

    def create(self, request):
        """
        Creates a key/pair in the Redis store.
        """
        print(request)
        # Serialize the request body
        serializer = KeysSerializer(data=request.data)

        # If valid, create the key/value in Redis; if not send error message
        if serializer.is_valid():
            return Response(self.redis_util.create(serializer.data))
        else:
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)

И utils.py, который обрабатывает действия Redis:

# utils.py

# Django imports
from django.conf import settings

# Redis imports
import redis


class RedisUtil:
    """
    Instantiates the Redis object and sets the connection params.
    """
    def __init__(self):
        self.redis_instance = redis.StrictRedis(
            host=settings.REDIS_HOST,
            port=settings.REDIS_PORT
        )

    def create(self, data):
        """
        Creates the key/value pair from request body.
        """
        return self.redis_instance.set(data['key'], data['value'])

Ошибка, которую я получаю, следующая:

Found 1 test(s).
System check identified no issues (0 silenced).
{'key': 'hello', 'value': 'world'}
E
======================================================================
ERROR: test_create (core.tests.KeysViewSetTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/Users/cjones/Projects/test/kv-store/api/src/core/tests.py", line 19, in test_create
    created = self.view.create(self.json_object)
  File "/Users/cjones/Projects/test/kv-store/api/src/core/views.py", line 32, in create
    serializer = KeysSerializer(data=request.data)
AttributeError: 'dict' object has no attribute 'data'

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (errors=1)

Я знаю, из-за чего я получаю эту ошибку: KeysViewSet().create() в views.py ожидает, что объект, который я передаю, находится в request.data = {}, а его нет.

Решить это - вот что я пытаюсь выяснить.

Я знаю, что существует библиотека request, но не уверен, что мне нужно импортировать ее только для этого. У DRF есть несколько вариантов , включая APIRequestFactory, но они попытаются создать базу данных и создадут ошибку, так как попытаются подключиться к Redis, а это невозможно.

Как мне решить эту проблему?

В итоге для решения проблемы я сделал следующее:

# test.py

import unittest
from unittest.mock import patch

from core.views import KeysViewSet


class KeysViewSetTestCase(unittest.TestCase):

    def setUp(self):
        self.json_object = {'key': 'hello', 'value': 'world'}
        self.view = KeysViewSet()
        class Request:
            def __init__(self, data):
                self.data = data
        self.request = Request(self.json_object)


    def test_create(self):
        with patch('core.views.RedisUtil.create') as mocked_create:
            mocked_create.return_value.data = True

            created = self.view.create(self.request)

При этом я не уверен, что это желательное решение, поэтому я не хочу принимать его как правильный ответ. С нетерпением жду отзывов.

Вернуться на верх