简体   繁体   English

在python函数中模拟具有不同返回值的相同方法两次

[英]Mock same method with different return value called twice in a function in python

I have a method to be tested using pytest. 我有一种方法可以使用pytest进行测试。 The method is calling same database model twice. 该方法两次调用相同的数据库模型。

 def function:
    ids = database_model.object.filter(user="user1").filter(group="admin").values_list(ids, flat=True).allow_filtering()
    response_list = []
    unquie_ids = list(set(ids))
    for ids in unique_ids:
        response = database_model.object.filter(ids=ids).limit(1)
        for res in response:
            temp_dict = {}
            temp_dict['name'] = res.name
            temp_dict['description'] = res.description
            response_list.append(temp_dict)
   return response_list

This works well. 这很好。 I am tring to write unit test case for this. 我正打算为此编写单元测试用例。 As the same database_model requires return value twice. 由于相同的database_model需要两次返回值。 It does not work for me. 它对我不起作用。

  @patch('database_model')
  def test_function(mock_model):
      mock_model.objects.filter.return_value.filter.return_value.values_list.return_value.allow_filtering_return_value = [Mock_id]
      mock_model.objects.filter.limit.return_value = mock_dict

      response = function()

      assert len(response) > 0

mock_id and mock_dict are values created for test case. mock_id和mock_dict是为测试用例创建的值。 My question is first time i am assigning a return_value to mock_model.objects.filter.return_value.filter.return_value.values_list.return_value.allow_filtering.return_value to [Mock_id] which gets assigned properly. 我的问题是我第一次将return_value分配给[Mock_id]正确分配的嘲笑模型[mock_id]的嘲笑模型。对象。过滤器。返回值。过滤器。返回值。数值。清单。返回值。允许_过滤。返回值。 But the next line i am trying to assign a return_value again to the same method. 但是下一行我试图再次将return_value分配给相同的方法。 This takes as a magic mock object. 这作为魔术模拟对象。 So my test case fails because it is getting a empty list. 所以我的测试用例失败了,因为它得到了一个空列表。 I would like to know how can i assign two different return_values to the same method. 我想知道如何将两个不同的return_value分配给同一方法。

You should write a side_effect for database_model.object.filter mock that gives you a Mock() configured to return the correct ids list after a mock to use in for cycle. 您应该为database_model.object.filter模拟编写一个side_effect ,该模拟为您提供了一个Mock()Mock()配置为在模拟之后返回正确的ids列表以用于循环。

mock_filter_get_ids = Mock()
mock_filter_ids = Mock()
mock_model.objects.filter.side_effect = [mock_filter_get_ids, mock_filter_ids]
mock_filter_get_ids.filter.return_value.values_list.return_value.allow_filtering_return_value = [Mock_id]
mock_filter_ids.limit.return_value = mock_dict

But... 但...

Forget it: refactor your code, at least extract: 忘记了:重构代码,至少提取以下内容:

database_model.object.filter(user="user1").filter(group="admin").values_list(ids, flat=True).allow_filtering()

In something like get_user_ids() and 在类似get_user_ids()

database_model.object.filter(ids=ids).limit(1)

in get_ids_response() . get_ids_response()

You can mock the new methods and make your code simpler to read, simple to test means simple to read almost every time. 您可以模拟新方法并使代码更易于阅读,易于测试意味着几乎每次都易于阅读。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM