I am learning how to make an api endpoint and I am trying to write a test to see if a post request returns a 200 status code. I plan on writing more tests to see if the endpoint is returning all the expected results as well. I keep getting a 403 status code and I think it is because I need to include a csrf token in the post data. What is a good way to test a POST endpoint in django?
my Test:
from django.test import TestCase from app import settings import requests class ProjectEndpoint(TestCase): def post_endpoint(self): data = {'hello':'23'} post_project = requests.post(settings.BASE_URL+'/api/project', params=data) self.assertEqual(post_endpoint.status_code, 200)
This test keeps failing with 403 != 200
I think it is because the view is protected against csrf attacks, but I am really not sure. Appreciate any insight that someone has.
import sys import requests URL = 'https://portal.bitcasa.com/login' client = requests. session() # Retrieve the CSRF token first client. get(URL) # sets cookie if 'csrftoken' in client.
csrf_token. Django has a {% csrf_token %} tag that is implemented to avoid malicious attacks. It generates a token on the server-side when rendering the page and makes sure to cross-check this token for any requests coming back in. If the incoming requests do not contain the token, they are not executed.
You need to set it as a header in the request, not in the body. X-CSRFToken is the key and the value is CSRF token from the cookie. This will work if you are using an API framework like Tastypie or Django Rest Framework .
Actually, django doesn't enforce (by default) csrf checking with tests, as per https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#testing:
The CsrfViewMiddleware will usually be a big hindrance to testing view functions, due to the need for the CSRF token which must be sent with every POST request. For this reason, Django’s HTTP client for tests has been modified to set a flag on requests which relaxes the middleware and the csrf_protect decorator so that they no longer rejects requests. In every other respect (e.g. sending cookies etc.), they behave the same.
If, for some reason, you want the test client to perform CSRF checks, you can create an instance of the test client that enforces CSRF checks:
from django.test import Client
csrf_client = Client(enforce_csrf_checks=True)
However, this does require you to be using the Django Client vs requests; as far as I know, Django doesn't mock/instrument/etc. requests... so you're actually hitting the real server when you run that unit test.
Also note that you should name your test functions something that starts with test_
So something like this (when run through django manage.py test .ProjectEndpoint)
def test_post_endpoint(self): data = {'hello':'23'} c = Client() #above, from django.test import TestCase,Client #optional, but may be necessary for your configuration: c.login("username","password") response = c.post('/api/project',params=data) self.assertEqual(response.status_code, 200)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With