如何在没有命中数据库的情况下使用django进行单元测试?

时间:2015-10-23 11:55:23

标签: python django unit-testing django-testing

我试图在没有实际访问数据库的情况下测试我的模型,但是当存在关系且相关实例不在数据库中时,Django显然无法创建模型。

有解决方法吗?

修改

这是我的代码:

from django.contrib.auth import models as auth_models

from app.models import Question, Category

user1 = auth_models.User(username='foo', first_name='Foo', last_name='Oof', email='foo@oof.com')
category = Category(name='sample-category')
question = Question(author=user1, category=category, title='sample-title')

给出了:

$ python manage.py test app.unittests.test_models

Traceback (most recent call last):
  File "manage.py", line 10, in <module>
    execute_from_command_line(sys.argv)
  File "venv2.7/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
    utility.execute()
  File "venv2.7/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 330, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "venv2.7/local/lib/python2.7/site-packages/django/core/management/commands/test.py", line 30, in run_from_argv
    super(Command, self).run_from_argv(argv)
  File "venv2.7/local/lib/python2.7/site-packages/django/core/management/base.py", line 390, in run_from_argv
    self.execute(*args, **cmd_options)
  File "venv2.7/local/lib/python2.7/site-packages/django/core/management/commands/test.py", line 74, in execute
    super(Command, self).execute(*args, **options)
  File "venv2.7/local/lib/python2.7/site-packages/django/core/management/base.py", line 441, in execute
    output = self.handle(*args, **options)
  File "venv2.7/local/lib/python2.7/site-packages/django/core/management/commands/test.py", line 90, in handle
    failures = test_runner.run_tests(test_labels)
  File "venv2.7/local/lib/python2.7/site-packages/django/test/runner.py", line 209, in run_tests
    suite = self.build_suite(test_labels, extra_tests)
  File "venv2.7/local/lib/python2.7/site-packages/django/test/runner.py", line 121, in build_suite
    tests = self.test_loader.loadTestsFromName(label)
  File "/usr/lib/python2.7/unittest/loader.py", line 91, in loadTestsFromName
    module = __import__('.'.join(parts_copy))
  File "myapp/unittests/test_models.py", line 8, in <module>
    question = Question(author=user1, category=category, title='sample-title')
  File "venv2.7/local/lib/python2.7/site-packages/django/db/models/base.py", line 468, in __init__
    setattr(self, field.name, rel_obj)
  File "venv2.7/local/lib/python2.7/site-packages/django/db/models/fields/related.py", line 668, in __set__
    (value, self.field.rel.to._meta.object_name)
ValueError: Cannot assign "<User: foo>": "User" instance isn't saved in the database.

2 个答案:

答案 0 :(得分:0)

据我所知,Django测试在测试运行完毕后没有点击你的生产数据库 - Django creates a new database and destroys it。如果是这种情况,您是否保存用户模型是否重要?保存用户模型不会影响生产数据库,test命令将清除已创建的临时数据库。

答案 1 :(得分:0)

尝试使用工厂; DjangoModelFactory和工厂男孩

factories.py

from factory import DjangoModelFactory, SubFactory
from factory import post_generation


class User(DjangoModelFactory):
    class Meta:
        model = 'authapp.User'

    name = 'test_user...'


class Category(DjangoModelFactory):
    class Meta:
        model = 'yourapp.Category'

    @post_generation
    def create_questions(self, create, **kwargs):
        count = 3

        make_items = getattr(Question, 'create' if create else 'build')
        items = [make_items(category=self) for i in range(count)]

        # for build you have to add questions to django's object cache
        if not create:
            self._prefetched_objects_cache = {'question': items}


class Question(DjangoModelFactory):
    class Meta:
        model = 'yourapp.Question'

    category = SubFactory(Category)
    user = SubFactory(User)

tests.py:

category = Category.build()

这将为用户创建一个类别和3个问题。您也可以不使用SunFactories并单独创建它们,只需使用.build(); 使用.build()时你不会命中数据库 - build会调用object的 init ()方法,但是没有命中save()方法

https://factoryboy.readthedocs.io/en/latest/