简体   繁体   English

Mocking 请求 object 传递给 ViewSet create() 方法

[英]Mocking a request object to pass to ViewSet create() method

I'm learning unittest and unittest.mock , and struggling with the concepts and implementations primarily with mock .我正在学习unittestunittest.mock ,并且主要在mock的概念和实现上苦苦挣扎。

For context, what I'm playing with is a Django / DRF API and Redis. I'm trying to write tests which require mocking the Redis calls.对于上下文,我正在玩的是 Django / DRF API 和 Redis。我正在尝试编写需要 mocking Redis 调用的测试。

Here is the test I'm working on:这是我正在进行的测试:

# 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)

The views.py : 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)

And the utils.py that handles the Redis actions:以及处理 Redis 操作的utils.py

# 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'])

The error I'm getting is the following:我得到的错误如下:

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)

I know what I'm getting this error: the KeysViewSet().create() in views.py is expecting the object I'm passing to be at request.data = {} and it isn't.我知道我收到此错误的原因: views.py中的KeysViewSet().create()期望我传递的 object 位于request.data = {} ,但事实并非如此。

Resolving it is what I'm trying to figure out.解决它是我想要弄清楚的。

I know there is the request library, but not sure I would need to import it just for this.我知道有request库,但不确定我是否需要为此导入它。 DRF has several options including APIRequestFactory, but those will try to spin up a database and create an error as it will try to connect to Redis which it won't be able to. DRF 有几个选项,包括 APIRequestFactory,但这些选项将尝试启动数据库并创建错误,因为它将尝试连接到 Redis,但它无法连接。

How should I go about resolving this issue?我go应该怎么解决这个问题?

What I ended up doing to resolve the issue was the following:我最终为解决该问题所做的工作如下:

# 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)

That being said, I'm not sure that this is a desirable solution so I'm reluctant to accept it as the correct answer.话虽如此,我不确定这是一个理想的解决方案,所以我不愿意接受它作为正确答案。 Looking forward to feedback.期待反馈。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM