I built up further on daniel's answer and have come up with a more detailed answer and code
- I have created a baseclass which can be used across all tests.py in rest of the module which would usually be in
common/tests.py
class BaseTestCase(TestCase):
def __create_authorization_header(self, token):
'''Properly Format the authorization token'''
return "Bearer {0}".format(token)
def __create_token(self, user):
'''Create an OAuth application for the test db and generate access token'''
app = Application.objects.create(
client_type=Application.CLIENT_CONFIDENTIAL,
authorization_grant_type=Application.GRANT_PASSWORD,
name='dummy',
user=user
)
unique_token = str(uuid.uuid4())
access_token = AccessToken.objects.create(
user=user,
scope='read write',
expires=timezone.now() + timezone.timedelta(seconds=300),
token=unique_token,
application=app
)
return access_token.token
def setUp(self) -> None:
self.client = APIClient()
self.factory = RequestFactory()
self.request = self.factory.get('/some-url/')
# create a user with readonly access
self.readonly_user = CustomUser(
username='readonly', email='[email protected]')
self.readonly_user.set_password('dummy_password')
self.readonly_user.save()
# create a user with admin access
self.admin_user = CustomUser(
username='admin', email='[email protected]')
self.admin_user.set_password('dummy_password')
self.admin_user.save()
#create your own permissions or add the existing ones here
#create permissions for model Project
content_type = ContentType.objects.get_for_model(Project)
self.view_project = Permission.objects.create(
codename='view_project', name='Can view my model', content_type=content_type)
#get the existing ones
self.view_project = Permission.objects.get(codename="view_project")
self.add_project = Permission.objects.get(codename="add_project")
#add it to your user
self.readonly_user.user_permissions.add(self.view_project)
self.admin_user.user_permissions.add(self.add_project)
self.readonly_token = self.__create_token(self.readonly_user)
self.admin_token = self.__create_token(self.admin_user)
self.readonly_token = self.__create_authorization_header(self.readonly_token
)
self.admin_token = self.__create_authorization_header(self.admin_token)
def tearDown(self):
AccessToken.objects.filter(token=self.readonly_token).delete()
AccessToken.objects.filter(token=self.admin_token).delete()
Application.objects.filter(name='itsupport_readonly').delete()
Application.objects.filter(name='itsupport').delete()
super().tearDown()
And tests.py for each of your module would inherit the above class and build upon it. Example
class ExampleTestCase(BaseTestCase):
def setUp(self) -> None:
return super().setUp()
def tearDown(self):
super().tearDown()
def test_create_item(self):
self.client.credentials(HTTP_AUTHORIZATION=self.admin_token)
response = self.client.post(
"/api/v1/item/", data={"name": "item_1"}, format='json')
self.assertEqual(response.status_code, 201)
def test_create_item_readonly(self):
self.client.credentials(HTTP_AUTHORIZATION=self.readonly_token)
response = self.client.post(
"/api/v1/item/", data={"name": "item_2"}, format='json')
self.assertEqual(response.status_code, 403)
The first test_case test_create_item
should return a 201 and the second test_case test_create_item_readonly
should return a 403