在 Django TestCase 中调用超级方法导致 RecursionError

Calling super method in Django TestCase causes RecursionError

根据Django's document

Warning

SimpleTestCase and its subclasses (e.g. TestCase, ...) rely on setUpClass() and tearDownClass() to perform some class-wide initialization (e.g. overriding settings). If you need to override those methods, don’t forget to call the super implementation:

class MyTestCase(TestCase):

    @classmethod
    def setUpClass(cls):
        super(MyTestCase, cls).setUpClass()
        ...

    @classmethod
    def tearDownClass(cls):
        ...
        super(MyTestCase, cls).tearDownClass()

......

我决定在编写测试时遵循这种做法:

class AuthorListViewTest(TestCase):

    @classmethod
    def setUpTestData(cls):
        number_of_authors = 13
        for author_num in range(number_of_authors):
            Author.objects.create(first_name='Christian %s' % author_num, last_name='Surname %s' % author_num,)
        super(AuthorListViewTest, cls).setUpTestData()

    # testing functions

但是当 运行 测试时我得到一个 RecursionError:

  <hundreds of identical lines omitted>
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 10, in setUpTestData
    super(AuthorModelTest, cls).setUpClass()
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 10, in setUpTestData
    super(AuthorModelTest, cls).setUpClass()
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 10, in setUpTestData
    super(AuthorModelTest, cls).setUpClass()
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 10, in setUpTestData
    super(AuthorModelTest, cls).setUpClass()
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 10, in setUpTestData
    super(AuthorModelTest, cls).setUpClass()
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 10, in setUpTestData
    super(AuthorModelTest, cls).setUpClass()
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 10, in setUpTestData
    super(AuthorModelTest, cls).setUpClass()
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 10, in setUpTestData
    super(AuthorModelTest, cls).setUpClass()
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 10, in setUpTestData
    super(AuthorModelTest, cls).setUpClass()
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 10, in setUpTestData
    super(AuthorModelTest, cls).setUpClass()
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/test/testcases.py", line 1025, in setUpClass
    cls.setUpTestData()
  File "/Users/sunqingyao/Documents/Projects/locallibrary/catalog/tests/test_models.py", line 9, in setUpTestData
    Author.objects.create(first_name='Big', last_name='Bob')
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/db/models/query.py", line 399, in create
    obj.save(force_insert=True, using=self.db)
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/db/models/base.py", line 796, in save
    force_update=force_update, update_fields=update_fields)
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/db/models/base.py", line 824, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/db/models/base.py", line 908, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/db/models/base.py", line 947, in _do_insert
    using=using, raw=raw)
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/db/models/query.py", line 1043, in _insert
    query = sql.InsertQuery(self.model)
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/db/models/sql/subqueries.py", line 177, in __init__
    super(InsertQuery, self).__init__(*args, **kwargs)
  File "/Users/sunqingyao/Envs/django_test/lib/python3.6/site-packages/django/db/models/sql/query.py", line 155, in __init__
    self.where = where()
RecursionError: maximum recursion depth exceeded

此错误在删除 super 行后得到修复。

这是为什么?我应该停止调用文档建议的超级实现吗?

从回溯来看,setUpTestData 似乎在父 class 中调用了 setUpClass。但是您的代码片段调用了 setUpTestData,这是正确的。