Django: Best way to unit-test an abstract model

后端 未结 13 1382
一个人的身影
一个人的身影 2020-12-24 12:28

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

13条回答
  •  情深已故
    2020-12-24 13:11

    Updated for Django >=2.0

    So I was running into a few problems using m4rk4l's answer: one being the 'RuntimeWarning: Model 'myapp.__test__mymodel' was already registered' issue brought up in one of the comments, another being tests failing because the table already exists.

    I've added a few checks to help solve these issues and now it works flawlessly. I hope this helps people

    from django.db import connection
    from django.db.models.base import ModelBase
    from django.db.utils import OperationalError
    from django.test import TestCase
    
    
    class AbstractModelMixinTestCase(TestCase):
        """
        Base class for tests of model mixins/abstract models.
        To use, subclass and specify the mixin class variable.
        A model using the mixin will be made available in self.model
        """
    
    @classmethod
    def setUpTestData(cls):
        # Create a dummy model which extends the mixin. A RuntimeWarning will
        # occur if the model is registered twice
        if not hasattr(cls, 'model'):
            cls.model = ModelBase(
                '__TestModel__' +
                cls.mixin.__name__, (cls.mixin,),
                {'__module__': cls.mixin.__module__}
            )
    
        # Create the schema for our test model. If the table already exists,
        # will pass
        try:
            with connection.schema_editor() as schema_editor:
                schema_editor.create_model(cls.model)
            super(AbstractModelMixinTestCase, cls).setUpClass()
        except OperationalError:
            pass
    
    @classmethod
    def tearDownClass(self):
        # Delete the schema for the test model. If no table, will pass
        try:
            with connection.schema_editor() as schema_editor:
                schema_editor.delete_model(self.model)
            super(AbstractModelMixinTestCase, self).tearDownClass()
        except OperationalError:
            pass
    

    To use, implement the same way as above (now with the correcting indentation):

    class MyModelTestCase(AbstractModelMixinTestCase):
        """Test abstract model."""
        mixin = MyModel
    
        def setUp(self):
            self.model.objects.create(pk=1)
    
        def test_a_thing(self):
            mod = self.model.objects.get(pk=1)
    

提交回复
热议问题