Expanding test coverage with ModelViewSetTestCase in Django Ninja CRUD
ModelViewSetTestCase
class ModelViewSetTestCase(django.test.TestCase)
A base class for testing ModelViewSet
subclasses in Django.
Provides automated validation, binding, and test method registration for subclasses,
ensuring comprehensive and consistent testing of ModelViewSet
instances.
Attributes:
model_viewset_class
Type[ModelViewSet] - The ModelViewSet subclass to test.base_path
str - The base path for the model views.
Example:
- Define your
ModelViewSet
and register its routes:
# examples/views/department_views.py
from ninja import Router
from ninja_crud import views, viewsets
from examples.models import Department
from examples.schemas import DepartmentIn, DepartmentOut
router = Router()
class DepartmentViewSet(viewsets.ModelViewSet):
model = Department
default_input_schema = DepartmentIn
default_output_schema = DepartmentOut
list_view = views.ListModelView()
create_view = views.CreateModelView()
retrieve_view = views.RetrieveModelView()
update_view = views.UpdateModelView()
delete_view = views.DeleteModelView()
DepartmentViewSet.register_routes(router)
- Include your router in your Ninja API configuration:
# config/api.py
from ninja import NinjaAPI
from examples.views.department_views import router as department_router
api = NinjaAPI(urls_namespace="api")
api.add_router("departments", department_router)
- Create your test class by subclassing
ModelViewSetTestCase
:
# examples/tests/test_department_views.py
from ninja_crud import testing
from examples.models import Department
from examples.views.department_views import DepartmentViewSet
class TestDepartmentViewSet(testing.viewsets.ModelViewSetTestCase):
model_viewset_class = DepartmentViewSet
base_path = "api/departments"
@classmethod
def setUpTestData(cls):
cls.department_1 = Department.objects.create(title="department-1")
cls.department_2 = Department.objects.create(title="department-2")
@property
def path_parameters(self):
return testing.components.PathParameters(
ok={"id": self.department_1.id},
not_found={"id": 9999}
)
@property
def payloads(self):
return testing.components.Payloads(
ok={"title": "department-3"},
bad_request={},
conflict={"title": self.department_2.title},
)
test_list_view = testing.views.ListModelViewTest()
test_create_view = testing.views.CreateModelViewTest(payloads)
test_retrieve_view = testing.views.RetrieveModelViewTest(path_parameters)
test_update_view = testing.views.UpdateModelViewTest(path_parameters, payloads)
test_delete_view = testing.views.DeleteModelViewTest(path_parameters)
Notes:
This class should not be instantiated directly. Instead, it should be subclassed.
It utilizes the __init_subclass__
method to perform automatic validation,
binding of AbstractModelViewTest
instances, and registration of test methods.
__init_subclass__
def __init_subclass__(cls, **kwargs)
Special method in Python that is automatically called when a class is subclassed.
For ModelViewSetTestCase
subclasses, this method is used to validate the class
attributes, bind the AbstractModelViewTest
instances to the subclass and to
their corresponding model views, and register the test methods. It should not be
called directly.