带有自定义身份验证的django rest测试视图
我尝试测试具有自定义身份验证的视图,主要是因为主身份验证基于外部登录注销系统,使用Redis作为数据库来存储会话 Auth类正在检查请求中的会话id,是否与Redis中的相同-如果是,则成功 My custom authentication.py看起来像:带有自定义身份验证的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
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请看下面的答案。