I need to write some unit tests for an abstract base model, that provides some basic functionality that should be used by other apps. It it would be necessary to define a mo
In Django 2.2, if you only have one abstract class to test, you can use the following:
from django.db import connection
from django.db import models
from django.db.models.base import ModelBase
from django.db.utils import ProgrammingError
from django.test import TestCase
from yourapp.models import Base # Base here is the abstract model.
class BaseModelTest(TestCase):
@classmethod
def setUpClass(cls):
# Create dummy model extending Base, a mixin, if we haven't already.
if not hasattr(cls, '_base_model'):
cls._base_model = ModelBase(
'Base',
( Base, ),
{ '__module__': Base.__module__ }
)
# Create the schema for our base model. If a schema is already
# create then let's not create another one.
try:
with connection.schema_editor() as schema_editor:
schema_editor.create_model(cls._base_model)
super(BaseModelTest, cls).setUpClass()
except ProgrammingError:
# NOTE: We get a ProgrammingError since that is what
# is being thrown by Postgres. If we were using
# MySQL, then we should catch OperationalError
# exceptions.
pass
cls._test_base = cls._base_model.objects.create()
@classmethod
def tearDownClass(cls):
try:
with connection.schema_editor() as schema_editor:
schema_editor.delete_model(cls._base_model)
super(BaseModelTest, cls).tearDownClass()
except ProgrammingError:
# NOTE: We get a ProgrammingError since that is what
# is being thrown by Postgres. If we were using
# MySQL, then we should catch OperationalError
# exceptions.
pass
This answer is only a tweaking of DSynergy's answer. One notable difference is that we are using setUpClass()
instead of setUpTestData()
. This difference is important since using the latter will result in InterfaceError
(when using PostgreSQL) or the equivalent in other databases when the other test cases are run. As to the reason why this happens, I do not know at the time of writing.
NOTE: If you have more than one abstract class to test, it is better to use the other solutions.