模拟请求.Session.get

时间:2020-08-31 20:02:30

标签: python django mocking

我有一个新的管理命令,该命令从URL中获取一个csv并将其保存在本地,然后对它进行一些处理并删除它。在我的“下载代码”中找到它的地方:

url = 'http://blahblahblah/output.csv'
with requests.Session() as s:
    download = s.get(url)
csv = open('temp_fallback.csv', 'wb')
csv.write(download.content)  # this works for url tests but not mock
csv.close()

对于真正的url来说,它的工作效果非常好,而且有些麻烦。我写了几个调用我的管理命令的单元测试,它们正在工作,但是现在我添加了一个单元测试,以使用模拟的响应而不是访问实时URL。我正在尝试这样,希望将发生的情况替换为request.Session.get):

@patch('requests.Session.get')
def test_mock_pass(self, mock_response):
    """ Test using mock response """
        
    test_response = {
        'content': 'bunch_of_content_here'
        'status_code': 200,
        'encoding': 'ISO-8859-1',
        'reason': 'OK',
        'elapsed': 'OK'
    }

    mock_response.return_value = test_response
    print("mock_response.return_value['content'] has: ", mock_response.return_value['content'])

    try:
        call_command('download_fallback_csv')
    except CommandError as e:
        self.fail("Failed download csv. {}".format(e))

但是调用URL时得到的响应与我要模拟的响应之间有些不同

  • 使用url的测试工作正常,但是此模拟测试在csv.write期间失败,并带有:“ AttributeError:'dict'对象没有属性'content'”
  • 但是,当我使用“可下标”表示法时,可以从测试内部看到内容:mock_response.return_value ['content'])
  • 如果我尝试更新我的“下载代码”以使用csv.write(download.meta ['content']),则会收到TypeError:'Response'对象无法下标,模拟:KeyError:'meta'< / li>

我觉得其中一部分代码的格式与其他代码略有不同,但是我不确定如何解决它-缺少的链接在哪里?

1 个答案:

答案 0 :(得分:1)

您可以将对象传递为dict,而不是传递test response。如下所示,

@patch('requests.Session.get')
def test_mock_pass(self, mock_response):
    """ Test using mock response """
    
    class TestResponse:
        def __init__(self, **kwargs):
            self.__dict__ = kwargs

    test_response = TestResponse(**{
        'content': 'bunch_of_content_here',
        'status_code': 200,
        'encoding': 'ISO-8859-1',
        'reason': 'OK',
        'elapsed': 'OK'
    })

    mock_response.return_value = test_response
    print("mock_response.return_value['content'] has: ", mock_response.return_value.content)

    try:
        call_command('download_fallback_csv')
    except CommandError as e:
        self.fail("Failed download csv. {}".format(e))

通过这种方式,您不必更改管理命令中的代码。