I have a few Django Rest Framework API endpoints I want to test.
They are behind an authenticated page. I'm trying to use the DRF RequestsClient
to do that.
My code looks like this:
from rest_framework.test import APITestCase
from rest_framework.test import RequestsClient
from django.urls import reverse
import requests
URL_PREFIX="http://testserver"
API_TOKEN="tfhgffhgf675h"
class APITests(APITestCase):
@staticmethod
def _get_full_url(url, *args, **kwargs):
return URL_PREFIX + reverse(url, *args, **kwargs)
def setUp(self):
self.client = RequestsClient()
def test_stuff(self):
url = self._get_full_url("ahs:agena_results-list")
# Raw requests library - works fine
# Note: Testing shows that the RequestsClient() seems to do some sort of magic to
# be able to resolve http://testserver. A raw requests GET request must hit it at
# 127.0.0.1, and specify the port
response = requests.get("http://127.0.0.1:8000", headers={"Authorization": f"Token {API_TOKEN}"})
# RequestsClient() - doesn't work
response = self.client.get(url, headers={"Authorization": f"Token {API_TOKEN}"})
My RequestsClient
request doesn't work, but my raw requests
request works fine.
The exception raised when using the RequestsClient
is pretty cryptic:
Internal Server Error: /ahs/api/agena_results/
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1361, in execute_sql
cursor.execute(sql, params)
File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 67, in execute
return self._execute_with_wrappers(
File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/usr/local/lib/python3.9/site-packages/django/db/backends/utils.py", line 83, in _execute
self.db.validate_no_broken_transaction()
File "/usr/local/lib/python3.9/site-packages/django/db/backends/base/base.py", line 480, in validate_no_broken_transaction
raise TransactionManagementError(
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/rest_framework/viewsets.py", line 125, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
response = self.handle_exception(exc)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
self.raise_uncaught_exception(exc)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
raise exc
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 497, in dispatch
self.initial(request, *args, **kwargs)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 414, in initial
self.perform_authentication(request)
File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 324, in perform_authentication
request.user
File "/usr/local/lib/python3.9/site-packages/rest_framework/request.py", line 227, in user
self._authenticate()
File "/usr/local/lib/python3.9/site-packages/rest_framework/request.py", line 380, in _authenticate
user_auth_tuple = authenticator.authenticate(self)
File "/usr/local/lib/python3.9/site-packages/rest_framework/authentication.py", line 196, in authenticate
return self.authenticate_credentials(token)
File "/usr/local/lib/python3.9/site-packages/rest_framework/authentication.py", line 201, in authenticate_credentials
token = model.objects.select_related('user').get(key=key)
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 492, in get
num = len(clone)
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 302, in __len__
self._fetch_all()
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 1507, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/usr/local/lib/python3.9/site-packages/django/db/models/query.py", line 57, in __iter__
results = compiler.execute_sql(
File "/usr/local/lib/python3.9/site-packages/django/db/models/sql/compiler.py", line 1364, in execute_sql
cursor.close()
File "/usr/local/lib/python3.9/site-packages/MySQLdb/cursors.py", line 83, in close
while self.nextset():
File "/usr/local/lib/python3.9/site-packages/MySQLdb/cursors.py", line 137, in nextset
nr = db.next_result()
MySQLdb._exceptions.OperationalError: (2006, '')
.
----------------------------------------------------------------------
Ran 1 test in 30.774s
The strange thing is that if I remove the Authorization
header from the RequestsClient
request, it doesn't crash, but does return a 403, so that doesn't help me.
I also tried setting the Authorization
header on the RequestsClient
this way, but that didn't help either:
self.client.headers.update({'Authorization': f'Token {API_TOKEN}'})
Any idea what I'm doing wrong?