drf - testing

Yerin·2020년 4월 15일
2

https://www.django-rest-framework.org/api-guide/testing/#making-requests

API Request Factory

creating test requests

from rest_framwork import APIRequestFactory

factory = APIRequestFactory()
request = factory.post('/notes/', {'title':'new idea'})
  • using the 'format' argument.
factory = APIRequestFactory()
request = factory.post('/notes/', {'title':'new idea'}, format = 'json')
  • explicitly encoding the request body
    content type 추가.
request = factory.post('/notes/', json.dumps({'title':'new idea'}), content_type='application/json')
  • put and patch with form dtat
  1. REST framework's APIRequestFactory
factory = APIRequestFactory()
request = factory.put('/notes/547/', {'title': 'remeber to email dave'})
  1. Django's RequestFactory
from django.test.client import encode_multipart, RequestFactory

factory = RequestFactory()
data = {'title': 'remember to email dave'}
content = encode_multipart('BoUnDaRyStRiNg', data)
content_type = 'multipart/form-data; boundary=BoUnDaRyStRiNg'
request = factory.put('/notes/547/', content, content_type=content_type)

forcing authentication

from rest_framework.test import force_authenticate

factory = APIRequestFactory()
user = User.objects.get(username='olivia')
view = AccountDetail.as_view()

request = factory.get('/accounts/django-superstars/')
force_authenticate(request, user=user)
response = view(request)
  • the signature of the method is 'force_authenticate(request, user=None, token=None)'. When making the call, either or both of the user and token may be set.

  • when forcibly authenticating using a token, you might do something like


user = User.objects.get(username='olivia')
request = factory.get('/accounts/django-superstars/')
force_authenticate(request, user=user, token=user.auth_token)
  • force_authenticate directly sets request.user to the in-memory user instance. If you are re-using the same user instance across multiple tests that update the saved user state, you may need to call refresh_from_db() between tests.

  • when using APIRequestFactory the object that is returned is django's standard HTTPRequest, and not REST framework's Request object, which is only generated once the view is called.


Forcing CSRF validation

  • requests created with APIRequestFactory will not have CSRF validation applied when passed to a REST framework view. You can do so by setting 'enforce_csrf_checks; flag when instantiating the factory
factory = APIRequestFactory(enforce_csrf_checks=True)
  • when using regular DJango the CSRF vlaidation takes place in middle ware, which is not run when testing views direclty. When using REST framework, csrf validation takes place inside the view, so the request factory needs to disable view-level csrf checks.

APIClient

making requests

from rest_framework.test import APIClient

client = APIClient()
client.post('/notes/', {'title':'new idea'}, format='json')

authenticating

  • the 'login' method functions exactly as it does with django's regular Client class. This allows you to authenticate requests against any views which include 'SessionAuthentication'.

  • login(**kwargs)

client = APIClient()
client.login(username='lauren', password='secret')
  • .credentials(**kwargs)
from rest_framework.authtoken.models import Token
from rest_framework.test import APIClient

token = Token.objects.get(user__username='lauren')
client= APIClient()
client.credentials(HTTP_AUTHORIZATION='Token' + token.key)
  • the credentials method is appropriate for testing apis that require authentication headers, such as basic authentication, oauth1 and oauth2 authentication, and simple token authentication schemes.

  • .force_authenticate(user=None, token=None)

sometimes you may want to bypass authentication entirely and force all requests by the test client to be automatically treated as authenticated.

user = User.objects.get(username='lauren')
client = APIClient()
client.force_authenticate(user=user)

RequestsClient

  • REST framework also includes a client for interacrting with your application using the requests library.
from rest_framework.test import RequestsClient

client = RequestsClient()
response = client.get('http://testserver/users/')
assert response.status_code == 200

RequestsClient and working with db

  • headers & authentication
from requests.auth import HTTPBasicAuth

client.auth = HTTPBasicAuth('user', 'pass')
client.headers.update({'x-test':'true'})
  • CSRF
client = RequestsClient()
response = client.get('http://testserver/homepage/')
assert response.status_code == 200
csrftoken = response.cookies['csrftoken']

#interact with the api
response = client.post('http://testserver/organisation/', json={ 
	'name': 'MegaCorp'.
    'status':'active'
    }, headers={'X-CSRFToken': csrftoken})
assert response.status_code == 200

live tests

  • both the RequestClient and the CoreAPIClient provide the ability to write test cases that can run either in development, or be run directly against your staging server or production environment.

CoreAPIClient

#fetch the api schema
client = CoreAPIClient()
schema = client.get('http://testserver/schema/')

#create new organisation
params = {'name':'MegaCorp', 'status':'active'}
client.action(schema, ['organisations', 'create'], params)

#ensure that the organisation exists in the listing
data = client.action(schema, ['organisations', 'list'])
assert(len(data)==1)
assert(data == [{'name':'MegaCorp', 'status':'active'}])

headers & authentication

  • custom headers and authentication may be used with CoreAPIClient in a similar way as with RequestsClient.
from request.auth import HTTPBasicAuth

client = CoreAPIClient()
client.session.auth = HTTPBasicAuth('user', 'pass')
client.session.headers.update({'x-test':'true'})

API Test cases

REST framework includes the following test cases, that mirror existing django test case classes, but use APIClient instead of django's default Client.

profile
졸꾸 !!!

0개의 댓글