有模拟 Django 模型的标准方法吗?
Is there a standard way to mock Django models?
我有一个名为 Pdb
的模型:
class Pdb(models.Model):
id = models.TextField(primary_key=True)
title = models.TextField()
与模型是一对多的关系Residue
:
class Residue(models.Model):
id = models.TextField(primary_key=True)
name = models.TextField()
pdb = models.ForeignKey(Pdb)
单元测试 Pdb
没问题:
def test_can_create_pdb(self):
pdb = Pdb(pk="1XXY", title="The PDB Title")
pdb.save()
self.assertEqual(Pdb.objects.all().count(), 1)
retrieved_pdb = Pdb.objects.first()
self.assertEqual(retrieved_pdb, pdb)
当我进行单元测试时 Residue
我只想使用模拟 Pdb 对象:
def test_can_create_residue(self):
pdb = Mock(Pdb)
residue = Residue(pk="1RRRA1", name="VAL", pdb=mock_pdb)
residue.save()
但这失败了,因为它需要一些名为 _state
:
的属性
AttributeError: Mock object has no attribute '_state'
所以我不断添加模拟属性,使它看起来像一个真实的模型,但最终我得到:
django.db.utils.ConnectionDoesNotExist: The connection db doesn't exist
我不知道如何模拟对数据库的实际调用。有没有标准的方法来做到这一点?我真的不想在测试数据库中实际创建 Pdb 记录,因为这样测试就不会被隔离。
是否有既定的最佳实践方法来做到这一点?
我为此获得的大多数 SF 和 google 结果都与模拟模型的特定方法有关。任何帮助将不胜感激。
哦,我设法用一个名为 'mixer'...
的库解决了这个问题
from mixer.backend.django import mixer
def test_can_create_residue(self):
mock_pdb = mixer.blend(Pdb)
residue = Residue(pk="1RRRA1", name="VAL", pdb=mock_pdb)
residue.save()
仍然认为 django 应该提供一种本机方法来执行此操作。它已经提供了很多测试工具 - 这感觉像是正确单元测试的主要部分。
你这里不是严格的单元测试,因为你涉及数据库,我会称之为集成测试,但这是另一个非常激烈的争论!
我的建议是让您的包装测试 class 继承自 django.test.TestCase。如果您担心每个单独的测试用例都被完全隔离,那么您可以使用每个 class.
的测试方法创建多个 classes
可能还值得重新考虑是否需要编写这些测试,因为它们似乎只是在验证框架是否正常工作。
我不确定您所说的模拟 Django 模型到底是什么意思。编写需要某些模型对象的测试的最简单选择是使用 test fixture。它基本上是一个 YAML 文件,在测试运行之前被加载到数据库中 table。
在 you mentioned mixer 中,它看起来像是一个用于随机生成那些测试装置的库。
这些都是很好的工具,但它们仍然需要数据库访问,而且它们比纯单元测试慢很多。如果您想完全模拟数据库访问,请尝试 Django mock queries。它完全模拟了数据库访问层,所以速度非常快,而且你不用担心外键。当我想测试一些具有简单数据库访问的复杂代码时,我会使用它。如果数据库访问有一些复杂的查询条件,那我还是用真实的数据库。
完全披露:我是 Django 模拟查询项目的次要贡献者。
我有一个名为 Pdb
的模型:
class Pdb(models.Model):
id = models.TextField(primary_key=True)
title = models.TextField()
与模型是一对多的关系Residue
:
class Residue(models.Model):
id = models.TextField(primary_key=True)
name = models.TextField()
pdb = models.ForeignKey(Pdb)
单元测试 Pdb
没问题:
def test_can_create_pdb(self):
pdb = Pdb(pk="1XXY", title="The PDB Title")
pdb.save()
self.assertEqual(Pdb.objects.all().count(), 1)
retrieved_pdb = Pdb.objects.first()
self.assertEqual(retrieved_pdb, pdb)
当我进行单元测试时 Residue
我只想使用模拟 Pdb 对象:
def test_can_create_residue(self):
pdb = Mock(Pdb)
residue = Residue(pk="1RRRA1", name="VAL", pdb=mock_pdb)
residue.save()
但这失败了,因为它需要一些名为 _state
:
AttributeError: Mock object has no attribute '_state'
所以我不断添加模拟属性,使它看起来像一个真实的模型,但最终我得到:
django.db.utils.ConnectionDoesNotExist: The connection db doesn't exist
我不知道如何模拟对数据库的实际调用。有没有标准的方法来做到这一点?我真的不想在测试数据库中实际创建 Pdb 记录,因为这样测试就不会被隔离。
是否有既定的最佳实践方法来做到这一点?
我为此获得的大多数 SF 和 google 结果都与模拟模型的特定方法有关。任何帮助将不胜感激。
哦,我设法用一个名为 'mixer'...
的库解决了这个问题from mixer.backend.django import mixer
def test_can_create_residue(self):
mock_pdb = mixer.blend(Pdb)
residue = Residue(pk="1RRRA1", name="VAL", pdb=mock_pdb)
residue.save()
仍然认为 django 应该提供一种本机方法来执行此操作。它已经提供了很多测试工具 - 这感觉像是正确单元测试的主要部分。
你这里不是严格的单元测试,因为你涉及数据库,我会称之为集成测试,但这是另一个非常激烈的争论!
我的建议是让您的包装测试 class 继承自 django.test.TestCase。如果您担心每个单独的测试用例都被完全隔离,那么您可以使用每个 class.
的测试方法创建多个 classes可能还值得重新考虑是否需要编写这些测试,因为它们似乎只是在验证框架是否正常工作。
我不确定您所说的模拟 Django 模型到底是什么意思。编写需要某些模型对象的测试的最简单选择是使用 test fixture。它基本上是一个 YAML 文件,在测试运行之前被加载到数据库中 table。
在
这些都是很好的工具,但它们仍然需要数据库访问,而且它们比纯单元测试慢很多。如果您想完全模拟数据库访问,请尝试 Django mock queries。它完全模拟了数据库访问层,所以速度非常快,而且你不用担心外键。当我想测试一些具有简单数据库访问的复杂代码时,我会使用它。如果数据库访问有一些复杂的查询条件,那我还是用真实的数据库。
完全披露:我是 Django 模拟查询项目的次要贡献者。