Python unittest.mock 图书馆

Python unittest.mock library

我正在为请求库编写单元测试。对于我的大多数图书馆,我 运行 在响应中 .content.decode('utf-8') 以获取实际文本。但是,当我从 api 调用中模拟此响应时,如何模拟请求调用接收到的响应对象?是否有一个 requests.content.encode('utf-8',data)) 看起来相似的过程,它实际上可以模拟来自 API 调用的响应(以编码格式),然后我解码该对象。

示例代码:

def sample_fct(self, endpoint):
    try:
        request = requests.post (endpoint, verify=False)
    except requests.exceptions.RequestException as e:
        raise
    return request

def get_something(self,test):
    try:
        response = self.sample_fct(test)
        resp_text = response_bare.content.decode('utf-8')
        print resp_text
    except:
        raise 

例如,如果我想对 get_something 函数进行单元测试,我需要模拟 sample_fct 函数。为此,我必须将 sample_fct.return_value 设置为它返回的请求对象。

那么如何创建该对象。

这里是您可以像我上面所说的那样模拟响应的方法。请注意,我采取了一些自由来使您的代码和我的测试真正起作用。它们包含在评论中:

"""request_module.py"""
import requests


class SomeClass(object):
    """I put these in a class, since you had self as your first arg"""
    def sample_fct(self, endpoint):
        try:
            request = requests.post (endpoint, verify=False)
        except requests.exceptions.RequestException as e:
            raise
        return request

    def get_something(self, test):
        try:
            response = self.sample_fct(test)
            resp_text = response.content.decode('utf-8')
            # Changed to return the value instead of print it
            return resp_text
        except:
            raise 

您可以在测试中看到我如何将模拟 sample_fct 的 return 值分配给任意 Mock 对象。该对象可以具有分配给它的任意属性,这有助于测试可能有许多属性级别深的 return 值。

"""test_request_module.py"""
import unittest
import unittest.mock as mock

from request_module import SomeClass

class TestRequests(unittest.TestCase):
    @mock.patch('request_module.SomeClass.sample_fct')
    def test_get_something(self, mock_sample_fct):
        mock_sample_fct.return_value = mock.Mock(content=b'some content you want to decode \xE2\x98\xBA')
        # Testing that your decoded value is returned
        some_class = SomeClass()
        result = some_class.get_something('some_test_value')
        # Note the decoded smiley face
        self.assertEqual('some content you want to decode ☺', result)

请注意,您还可以在 Mock 上分配属性的属性。因此,如果您的来电者期望像 request.attributes.nested_attributes.value 这样的事情,您可以这样做,并且 Mock 将允许它:

mock_ret = mock.Mock()
mock_ret.request.attributes.nested_attributes.value = 'deep attr value'