Reputation: 1677
I am trying to find out the best way for testing admin.ModelAdmin
in admin.py
. Specifically I am overriding the save_model()
function which I want to test. From the research I have done, the only solution I have found was writing a request/response test and then query the database.
Upvotes: 75
Views: 40513
Reputation: 1428
To test if the search does not lead to server errors (i.e. because search_fields
are not correct) you can use the following code:
from django.contrib import admin
from django.contrib.auth.models import User
from django.test import TestCase
from django.urls import reverse
class TestModelAdmins(TestCase):
def test_search_fields(self):
user_1 = User(
username="user1",
first_name="User",
last_name="One",
email="[email protected]",
password="superSecurePasswordFromStackoverflow",
is_superuser=True,
is_staff=True,
)
user_1.full_clean()
user_1.save()
self.client.force_login(user_1)
for model_class, admin_class in admin.site._registry.items():
with self.subTest(model_class._meta.model_name):
path = reverse("admin:%s_%s_changelist" % (model_class._meta.app_label, model_class._meta.model_name))
response = self.client.get(path + "?q=blub")
self.assertEqual(response.status_code, 200)
Upvotes: 1
Reputation: 14255
As suggested in Udi's answer, we can study Django's own ModelAdmin tests, to determine the basic ingredients for a ModelAdmin
test. Here's a summary:
In addition to the Django TestCase
stuff, the basic ingredients are:
An instance of AdminSite
:
from django.contrib.admin.sites import AdminSite
Your model class and corresponding ModelAdmin
(sub)class:
from my_app.models import MyModel
from my_app.admin import MyModelAdmin
Optionally, depending on your needs, a (mock) request and/or form.
The first two ingredients are required to create an instance of your (custom) ModelAdmin
:
my_model_admin = MyModelAdmin(model=MyModel, admin_site=AdminSite())
Based on the ModelAdmin source, the default save_model
implementation only requires an instance of your model, so it can be called, for example, as follows:
my_model_admin.save_model(obj=MyModel(), request=None, form=None, change=None)
# some test assertions here
It all depends on what your save_model
does, and what you want to test.
Suppose your save_model
checks user permissions, then you would need to provide a request
(i.e. the third ingredient) with a valid user, in addition to the model instance:
from unittest.mock import Mock
...
my_user = User.objects.create(...)
my_model_admin.save_model(
obj=MyModel(), request=Mock(user=my_user), form=None, change=None
)
# some test assertions here
Here we use unittest.mock.Mock
to create a mock-request. Based on the Django test source, a minimal request
consists of a Python object
with a user
attribute.
The user
attribute may refer to a mock user, or an actual instance of your AUTH_USER_MODEL
, depending on your needs. An alternative would be to use django.test.RequestFactory.
This basic approach applies to the other ModelAdmin
methods as well.
Upvotes: 88
Reputation: 11798
You can specify custom modelform for modeladmin then simply test this modelform ;)
https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form
forms
class SomeModelForm(forms.ModelForm):
class Meta:
model = SomeModel
admin
class SomeModelAdmin(admin.ModelAdmin):
form = SomeModelForm
admin.site.register(SomeModel, SomeModelAdmin)
tests
class TestSomeModel(TestCase):
def test_form(self):
form = SomeModelForm(**kwargs)
self.assertTrue(form.is_valid())
# ...
Upvotes: 6