Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vue.js/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有自定义身份验证的django rest测试视图_Django_Authentication_Django Rest Framework - Fatal编程技术网

带有自定义身份验证的django rest测试视图

带有自定义身份验证的django rest测试视图,django,authentication,django-rest-framework,Django,Authentication,Django Rest Framework,我尝试测试具有自定义身份验证的视图,主要是因为主身份验证基于外部登录注销系统,使用Redis作为数据库来存储会话 Auth类正在检查请求中的会话id,是否与Redis中的相同-如果是,则成功 My custom authentication.py看起来像: from django.utils.six import BytesIO from rest_framework import authentication from rest_framework import exceptions fr

我尝试测试具有自定义身份验证的视图,主要是因为主身份验证基于外部登录注销系统,使用Redis作为数据库来存储会话

Auth类正在检查请求中的会话id,是否与Redis中的相同-如果是,则成功

My custom authentication.py看起来像:

from django.utils.six import BytesIO

from rest_framework import authentication
from rest_framework import exceptions

from rest_framework.parsers import JSONParser

import redis


class RedisAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):

    print(request.META)
    token = request.META['HTTP_X_AUTH_TOKEN']
    redis_host = "REDIS_IP_ADRESS"
    redis_db = redis.StrictRedis(host=redis_host)
    user_data = redis_db.get("user_feature:{}".format(token))
    if user_data is None:
        raise exceptions.AuthenticationFailed('No such user or session expired')

    try:
        stream = BytesIO(user_data)  # Decode byte type
        data = JSONParser(stream)  # Parse bytes class and return dict
        current_user_id = data['currentUserId']
        request.session['user_id'] = current_user_id
    except Exception as e:
        print(e)

    return (user_data, None)
@api_view(['GET', 'POST'])
@authentication_classes((RedisAuthentication, ))
def task_list(request):
    if request.method == 'GET':
        paginator = PageNumberPagination()
        task_list = Task.objects.all()
        result_page = paginator.paginate_queryset(task_list, request)
        serializer = TaskSerializer(result_page, many=True)
        return paginator.get_paginated_response(serializer.data)

    elif request.method == 'POST':
        serializer = PostTaskSerializer(data=request.data)
        if serializer.is_valid():
            user_id = request.session.get('user_id')
            serializer.save(owner_id=user_id)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
my views.py看起来像:

from django.utils.six import BytesIO

from rest_framework import authentication
from rest_framework import exceptions

from rest_framework.parsers import JSONParser

import redis


class RedisAuthentication(authentication.BaseAuthentication):
    def authenticate(self, request):

    print(request.META)
    token = request.META['HTTP_X_AUTH_TOKEN']
    redis_host = "REDIS_IP_ADRESS"
    redis_db = redis.StrictRedis(host=redis_host)
    user_data = redis_db.get("user_feature:{}".format(token))
    if user_data is None:
        raise exceptions.AuthenticationFailed('No such user or session expired')

    try:
        stream = BytesIO(user_data)  # Decode byte type
        data = JSONParser(stream)  # Parse bytes class and return dict
        current_user_id = data['currentUserId']
        request.session['user_id'] = current_user_id
    except Exception as e:
        print(e)

    return (user_data, None)
@api_view(['GET', 'POST'])
@authentication_classes((RedisAuthentication, ))
def task_list(request):
    if request.method == 'GET':
        paginator = PageNumberPagination()
        task_list = Task.objects.all()
        result_page = paginator.paginate_queryset(task_list, request)
        serializer = TaskSerializer(result_page, many=True)
        return paginator.get_paginated_response(serializer.data)

    elif request.method == 'POST':
        serializer = PostTaskSerializer(data=request.data)
        if serializer.is_valid():
            user_id = request.session.get('user_id')
            serializer.save(owner_id=user_id)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
手动测试通过,但我当前的pytests在添加authentication.py后失败,并且不知道如何正确修复它-尝试了强制auth,但没有成功。 我认为解决方案之一是使用fakeredis来模拟真实的redis。问题是,这种测试应该是什么样的

您可以在此处找到测试示例:

@pytest.mark.webtest
class TestListView(TestCase):
    def setUp(self):
        self.client = APIClient()
    def test_view_url_accessible_by_name(self):
        response = self.client.get(
            reverse('task_list')
        )
        assert response.status_code == status.HTTP_200_OK

@pytest.mark.webtest
class TestCreateTask(TestCase):
    def setUp(self):
        self.client = APIClient()
        self.user = User.objects.create_user(username='admin', email='xx', password='xx')
    def test_create(self):
        data = {some_data}
        self.client.login(username='xx', password='xx')
        response = self.client.post(
            reverse('task_list'),
            data,
            format='json')
        assert response.status_code == status.HTTP_201_CREATED
        self.client.logout()

提前感谢您的帮助

我使用mock.patch decorator-模拟了整个redis身份验证

将导入修补程序放入mock.patch decorator时,不要插入存储redis代码的绝对模块路径,而是插入作为模块导入并使用redis代码的路径

我的测试现在看起来是这样的:

@mock.patch('api.views.RedisAuthentication.authenticate')
def test_view_url_accessible_by_name(self, mock_redis_auth):

    data = {"foo": 1, "currentUserId": 2, "bar": 3}
    mock_redis_auth.return_value = (data, None)

    response = self.client.get(
        reverse('task_list'),
        HTTP_X_AUTH_TOKEN='foo'
    )
    assert response.status_code == status.HTTP_200_OK

你已经找到解决办法了吗?@javidazac请看下面的答案。