3👍
Simple Solution
So after a little digging and testing it seems that it’s best to let django’s TestCase
close the transaction normally and then remove the model from the test database. Essentially we just call the super().tearDownClass()
first instead of last.
ModelMixinTestCase
Since it’s a useful class I’ll post the full class for others to copy/paste.
class ModelMixinTestCase(TestCase):
"""
Test Case for abstract mixin models.
Subclass and set cls.mixin to your desired mixin.
access your model using cls.model.
"""
mixin = None
model = None
@classmethod
def setUpClass(cls) -> None:
# Create a real model from the mixin
cls.model = ModelBase(
"__Test" + cls.mixin.__name__,
(cls.mixin,),
{'__module__': cls.mixin.__module__}
)
# Use schema_editor to create schema
with connection.schema_editor() as editor:
editor.create_model(cls.model)
super().setUpClass()
@classmethod
def tearDownClass(cls) -> None:
# allow the transaction to exit
super().tearDownClass()
# Use schema_editor to delete schema
with connection.schema_editor() as editor:
editor.delete_model(cls.model)
# close the connection
connection.close()
Example Usage 1
class MyMixinTestCase(ModelMixinTestCase):
mixin = MyMixin
def test_true(self):
self.assertTrue(True)
Example Usage 2
class SortableModelMixinTestCase(ModelMixinTestCase):
mixin = SortableModelMixin
def setUp(self) -> None:
self.objects = [self.model.objects.create(pk=i) for i in range(10)]
def test_order_linear(self) -> None:
i = 1
for item in self.objects:
self.assertEqual(i, item.sortable_order)
i += 1
👤bob
0👍
@bob Thanks for the good solution, this worked great.
But when reusing the mixin on a different TestCase with the same model I ran into a warning:
RuntimeWarning: Model '<model_name>' was already registered. Reloading models is not advised as it can lead to inconsistencies, most notably with related models.
I solved this by checking if the model was already registered in the app:
@classmethod
def setUpClass(cls) -> None:
# Create a real model from the mixin or
# get it from the reqistered models if it already exist
model_name = "__Test" + cls.mixin.__name__
for app, models in apps.all_models.items():
if model_name.lower() in models:
cls.model = models[model_name.lower()]
if not hasattr(cls, "model"):
cls.model = ModelBase(
model_name, (cls.mixin,),
{'__module__': cls.mixin.__module__}
)
- [Django]-How to create 2 pages from reportlab using one PageTemplate?
- [Django]-Get first object from Django queryset
- [Django]-403 error when trying to backup AWS S3 database to heroku postgres
- [Django]-Schema validation failed; XML does not comply with UBL 2.1 standards in line with ZATCA specifications
Source:stackexchange.com