我有一个名为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和谷歌搜索结果与模拟模型的特定方法有关。任何帮助将不胜感激。
答案 0 :(得分:4)
由于您涉及数据库,因此您不是严格的单元测试,我会称之为集成测试,但这是另一个非常激烈的争论!
我的建议是让你的包装测试类继承自django.test.TestCase。如果您担心每个单独的测试用例被完全隔离,那么您可以使用每个类的测试方法创建多个类。
如果这些测试完全需要编写,也可能值得重新考虑,因为它们似乎只是在验证框架是否有效。
答案 1 :(得分:0)
哦,我设法通过一个名为“混音器”的库来解决这个问题......
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应该提供一种原生方式来做到这一点。它已经提供了许多测试工具 - 这感觉就像正确的单元测试的主要部分。
答案 2 :(得分:0)
我不确定你是什么意思嘲笑Django模型。编写需要某些模型对象的测试的最简单选项是使用test fixture。它基本上是一个在测试运行之前加载到数据库表中的YAML文件。
在your answer中你提到mixer,它看起来像是一个随机生成这些测试装置的库。
这些都是很好的工具,但它们仍然需要数据库访问,而且它们比纯单元测试要慢很多。如果您想完全模拟数据库访问,请尝试Django mock queries。它完全模拟了数据库访问层,因此速度非常快,您不必担心外键。当我想测试一些具有简单数据库访问权限的复杂代码时,我会使用它。如果数据库访问有一些复杂的查询条件,那么我坚持使用真正的数据库。
完全披露:我是Django模拟查询项目的次要贡献者。