我对单元测试非常陌生,并且想在我的Django应用程序中进行一些“简单”的初学者测试,我有一个带有“自定义”保存方法的模型,如果有新方法,它将调用外部api。无法在不调用外部API的情况下弄清楚如何建立该模型,该如何实现模拟解决方案?
class Task(models.Model):
status = models.CharField(max_length=25, choices=STATUS_CHOICES, default='new')
....
def _create(self):
....
return requests.post(API_URL + url, json=payload).json()
def save(self, *args, **kwargs):
is_new = self.created is None
super(Task, self).save(*args, **kwargs)
if is_new:
self._create()
class TaskTestCase(TestCase):
def setUp(self):
self.task = Task.objects.create(status='new')
def test_get_new_task(self):
task = Task.objects.all()[0]
self.assertEqual(task.status, 'new')
答案 0 :(得分:3)
这是python模拟库的典型用例。在您的情况下,我可能看起来像这样
import mock
class TaskTestCase(TestCase):
@mock.patch("request.post")
def setUp(self, mocked_post):
self.task = Task.objects.create(status='new')
def test_get_new_task(self):
task = Task.objects.all()[0]
self.assertEqual(task.status, 'new')
如果要在代码的特定部分上模拟函数调用,则可以将mock.patch用作装饰器,也可以用作上下文管理器。 See the documentation for more details。
在此示例中,我们仅嘲笑了该方法,以避免真正进行调用。在某些情况下,最好检查是否已调用模拟方法以及使用哪个参数。
import mock
class TaskTestCase(TestCase):
@mock.patch("request.post")
def setUp(self, mocked_post):
self.task = Task.objects.create(status='new')
# The most basic way to check a call was performed
mocked_post..assert_called()
# Checking the number of call can be a good idea
mocked_post.assert_called_once()
# Same idea but it also checks the arguments of the method.
mocked_post.assert_called_once_with()
最后一个选项对于测试您是否正在向外部服务发送正确的数据非常有用。有关不同选项in the documentation的更多详细信息。
模拟您可以在测试套件中进行的所有外部呼叫确实是一个好主意。原因如下: