来自相关对象

时间:2017-11-03 14:11:18

标签: python django unit-testing django-queryset django-testing

我有以下功能:

import unittest
from unittest import mock


def get_payments(order):
    return order.payments.filter(status='complete').order_by('-date_added)

我想模拟filter方法和order_by来检查调用的参数。

我试过了:

class TestPayments(unittest.TestCase):
     @mock.patch('path.Order.payments.filter.order_by')
     @mock.patch('path.Order.payments.filter')
     def test_get_payments(self, mock1, mock2):
        mock1.assert_called_with(status='complete')
        mock2.assert_called_with('-date_added')

我试过的另一个模拟:

@mock.patch('path.Payment.objects.filter.order_by')
@mock.patch('path.Payment.objects.filter')

@mock.patch('path.Order.payments.objects.filter.order_by')
@mock.patch('path.Order.payments.objects.filter')

在最后两次嘲笑中,我遇到path.Order不存在的错误。 我已经使用直接模拟来查找Payment.objects.filter()这样的查询并且正在运行,但是从Order这样的相关模型开始我失败了。

OrderPayment之间的关系是您所期望的,一对多。

2 个答案:

答案 0 :(得分:3)

通过模拟对象我解决了这个问题。

    order = MagicMock(side_effect=Order())
    order.payments.filter.return_value = MagicMock(side_effect=Payment.objects.filter(id=0))
    order.payments.filter.return_value.order_by.return_value = [Payment()]

    order.payments.filter.assert_called_with(status='complete')
    order.payments.filter.return_value.order_by.assert_called_with('-date_updated')

答案 1 :(得分:1)

要解释这里发生的事情:filter()exclude()order_by()等QuerySet方法返回一个QuerySet,这就是它们可以被链接的原因。

您首先尝试修补方法,就好像它们位于包层次结构中一样。你最终做的不是修补方法,而是模拟每个链式方法的返回值,这就是它的完成方式。

不幸的是,没有太多关于此的文档。当我遇到这个问题时,我有一些帮助我的stackoverflow答案,但我似乎无法再找到它们。

类似问题(答案并未真正提供解释):

有些库可能会对您有所帮助:mock-django提供了一个ORM模拟类。他们对mocking QuerySet methods的态度非常有趣。我个人认为测试Django模型非常有用的是Model Mommy,因为它可以帮助你创建简单的模型模型。