'Django rest framework: Unit testing post request gets status code 400
I'm doing some unit tests in this restaurant app, and the API request to cancel orders returns code 400 when running "manage.py test" command, but doing the same request on Postman works fine (with the server also running on my local machine with the "manage.py runserver" command). I think it's something I'm doing wrong with the unit test, but I'm not sure. In settings, Debug = True and ALLOWED_HOSTS = ['*'] (but I also tried ALLOWED_HOSTS = []). Here's the code:
tests.py
class CancelOrderAPITest(APITestCase):
def setUp(self):
test_product = Products.objects.create(id=1, name='testProduct', description='-test-', price=2.56)
test_product.save()
test_order = Order.objects.create(table=1, status='WA')
test_order.save()
test_order.product.add(test_product)
self.user = User.objects.create(username='test')
self.user.set_password('passtest')
self.user.save()
Payments.objects.create(value=0.0, user=self.user)
Token.objects.create(user=self.user)
def test_CancelWithCredentials(self):
check_login = self.client.login(username='test', password='passtest')
self.assertTrue(check_login)
token = Token.objects.get_or_create(user=self.user)
self.client.credentials(HTTP_AUTHORIZATION=f'Token {token[0].key}')
data = {"table": 1}
response = self.client.post(reverse('cancel-order'), data=data, content_type='application/json')
order = Order.objects.filter(table=data['table']).order_by('date')[0]
self.assertEqual(response.status_code, status.HTTP_200_OK) # returning 400. Investigate further
self.assertEqual(order.status, Order.Status.CANCELED)
views.py
class CancelOrder(APIView):
# REST API view for waiters to cancel orders. The waiter must be an authenticated user
permission_classes = (IsAuthenticated,)
parser_classes = (JSONParser,)
def post(self, request):
data = request.data
try:
order = Order.objects.filter(table=data['table']).order_by('date')[0]
order.status = Order.Status.CANCELED
order.save()
resp = {"status": "Order canceled!"}
except ObjectDoesNotExist:
resp = {"exception": "Couldn't find requested product!"}
return Response(resp)
models.py
class Order(models.Model):
class Status(models.TextChoices):
WAITING = 'WA', _('Waiting')
DELIVERED = 'DE', _('Delivered')
PARTIAL_DELIVER = 'PD', _('Partially Delivered')
PREPARING = 'PP', _('Preparing')
CANCELED = 'CA', _('Canceled')
PAID = 'PA', _('Paid')
product = models.ManyToManyField(Products)
table = models.IntegerField(default=1)
status = models.CharField(max_length=100, choices=Status.choices, default=Status.WAITING)
date = models.DateTimeField(default=datetime.datetime.now)
payment = models.ForeignKey(Payments, on_delete=models.DO_NOTHING, default=1)
Solution 1:[1]
I figured it out, thanks to the @annonymous comment.
For some reason the unit test was sending the data in the request with single quotes causing a parse error, even though I was declaring it with double quotes. Solved by removing the parameter content_type="application/json
and adding the parameter format="json"
to the request.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |