我是一名软件开发人员多年,但对 Python 还很陌生。我正在编写一个单元测试(因此不存在数据库连接),该测试涉及 Django 中的一个模型,该模型访问通过外键连接引用的另一个模型。我想模拟访问此连接的方法,并将结果替换为硬编码响应,但每个实例的响应都是不同的。
这是一个最小的例子:
### tests/test_MyTestCase.py
from unittest import TestCase
from djangoapi.models import *
class MyTestCase(TestCase):
def setUp(self):
self.instance1 = MyModel()
self.instance2 = MyModel()
foreignKey1 = MySubModel()
foreignKey1.my_value = 1
# Mock that self.instance1.submodel_set.all() returns [foreignKey1]
foreignKey2 = MySubModel()
foreignKey2.my_value = 2
# Mock that self.instance2.submodel_set.all() returns [foreignKey2]
def testSomething(self):
self.assertEqual(self.instance1.get_max_value(), 1)
self.assertEqual(self.instance2.get_max_value(), 2)
### models.py
from django.db import models
class MyModel(models.Model):
def get_max_value(self):
value = 0
# the return value of self.submodel_set.all() is what I want to mock
for model in self.submodel_set.all():
value = max(value, model.my_value)
return value
class Submodel(models.Model):
my_model = models.ForeignKey(MyModel, null=True, on_delete=models.SET_NULL)
my_value = models.IntegerField()
我尝试了
the @patch decorator
、Mock()
和 MagicMock()
的几种组合,但无法使其工作。预先感谢您!
经过更多研究,我发现主要问题是模拟不能在
setUp
方法中发生,而必须在测试方法本身中完成。这意味着一些代码重复,但至少现在可以工作了。作为参考,这是工作示例:
from unittest import TestCase
from unittest.mock import patch
from djangoapi.models import *
class MyTestCase(TestCase):
def setUp(self):
self.my_model = MyModel()
self.foreignKey1 = MySubModel()
self.foreignKey1.my_value = 1
self.foreignKey2 = MySubModel()
self.foreignKey2.my_value = 2
@patch('djangoapi.models.MyModel.submodel_set')
def testSomething(self, mock_submodel_set):
mock_submodel_set.all.return_value = [self.foreignKey1]
self.assertEqual(self.my_model.get_max_value(), 1)
mock_submodel_set.all.return_value = [self.foreignKey2]
self.assertEqual(self.my_model.get_max_value(), 2)