无法模拟数据库Django链查询

时间:2019-05-01 19:52:59

标签: python-3.x django-models mocking python-unittest

我正在尝试模拟Django链查询。这些是

 1. MyModel.objects.filter(userId=userId).exists()
 2. mrvDb = MyModel.objects.filter(userId=userId).order_by('-dateViewed')

我正在尝试模拟查询1。以下是我的方法

   @mock.patch('myapp.models.MyModel.objects')
   @mock.patch('myapp.models.MyModel.objects')
   def test_retrieveMRVListService(self, param, most_Recently_Viewed_List):

      mock_MRVList_data = mock.MagicMock(spec=MyModel)
      mock_MRVList_data.userId = 6
      mock_MRVList_data.policyId = 6
      most_Recently_Viewed_List.filter.return_value = [mock_MRVList_data]  

    # param.filter.return_value = param
    param.filter.exists.return_value = "True"

为此。我收到错误消息:(AttributeError:'list'      对象没有属性“存在”)

我正在尝试测试此方法。

def retrieveMRVListService(userId):
    if mostRecentlyViewedList.objects.filter(userId=userId).exists():
        mrvDb = mostRecentlyViewedList.objects.filter(
            userId=userId
            ).order_by('-dateViewed')[:5]
        mrvList = []
        for mrv in mrvDb:
            mrvData = {}
            mrvData["userId"] = mrv.userId
            mrvData["policyId"] = mrv.policyId
            mrvList.append(mrvData)
    else:
        mrvList = []
    return mrvList

我是unittest和模拟/测试Django查询的新手。任何人都可以帮助解决连锁查询。任何帮助或领导,我将不胜感激。 请让我知道是否需要任何信息。

1 个答案:

答案 0 :(得分:0)

您已经完成了大部分工作,这实际上是令人惊奇的,因为大多数使用Python的人甚至都不知道如何使用Mock。真正使您烦恼的是most_Recently_Viewed_List.filter.return_value实际上是List,它正确地指出它不具有“ exists”属性(因为它没有)。

因此请按步骤进行分解:

  1. MyModel.objects.filter(userId = userId)返回一个QuerySet对象。
  2. 然后,您在步骤1返回的QuerySet上调用exists()

因此,当您修补/模拟对象时,必须正确跟踪实际调用的内容和位置。

您可以做的是在步骤1中返回不同的Mock,然后修改该对象的返回调用,就好像它是原始的QuerySet

mock_queryset = Mock() # Create a mock of the QuerySet

# in Django calling filter() returns a QuerySet, so lets do that

most_Recently_Viewed_List.filter.return_value = mock_queryset

# now modify the return value for the calls you make on that queryset
mock_queryset.exists.return_value = True
mock_queryset.order_by.return_value = [mock_MRVList_data] # just like your original code

正如您所看到的,我们现在正在做的是模拟您在代码中调用的实际内容。