有没有一种标准方法来模拟Django模型?

4

我有一个名为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搜索结果都与模拟模型的特定方法有关。任何帮助将不胜感激。
3个回答

4

您在这里并不是严格的单元测试,因为您涉及到了数据库,我会称之为集成测试,但这是另一个非常激烈的争论!

我的建议是让您的包装测试类继承django.test.TestCase。如果您非常关注每个单独的测试用例完全隔离,那么您可以创建多个类,每个类有一个测试方法。

重新考虑是否需要编写这些测试,因为它们似乎只是验证框架是否正常工作。


我完全理解你的观点,只是测试框架是否正常工作 - 它非常接近这一点。我进行这些测试的理由是测试正确的字段是否存在且具有正确的字段类型,尽管我想这与测试常量非常接近。测试已经从Django TestCase继承,我只是在上面的片段中省略了它。谢谢! - Sam Ireland
就我个人而言,我会将那个测试留给后续更广泛的集成测试。编写覆盖微小细节的单元测试很容易让人陷入困境。我试着将它们视为黑匣子,其中入口点是公开使用的API。 - Tiger_Mike

0

我不确定您所说的模拟Django模型的确切含义。编写需要一些模型对象的测试的最简单选项是使用test fixture。它基本上是一个YAML文件,在您的测试运行之前加载到数据库表中。

您的答案中,您提到了mixer,它看起来像是用于随机生成这些测试fixture的库。

这些都是很好的工具,但它们仍然需要数据库访问,并且比纯单元测试慢得多。如果您想完全模拟数据库访问,请尝试Django mock queries。它完全模拟了数据库访问层,因此非常快速,而且您不必担心外键。当我想要测试一些具有简单数据库访问的复杂代码时,我会使用它。如果数据库访问具有一些复杂的查询条件,那么我会坚持使用真实的数据库。

完整披露:我是Django模拟查询项目的次要贡献者。


0

哦,我用一个叫做“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应该提供一种本地方法来完成这项工作。它已经提供了许多测试工具 - 这感觉像是适当的单元测试的重要组成部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接