[英]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
.我正在学习unittest
和unittest.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.