简体   繁体   English

Python unittest.mock库

[英]Python unittest.mock library

I'm writing unit tests for a requests library. 我正在为请求库编写单元测试。 For most of my libraries, I run a .content.decode('utf-8') on the response to get to the actual text. 对于我的大多数库,我在响应上运行.content.decode('utf-8')以获取实际文本。 However when I'm mocking this response from the api call, how do I mock a response object which is received by the requests call? 但是,当我模拟来自api调用的响应时,如何模拟请求调用接收到的响应对象? is there a requests.content.encode('utf-8',data)) look alike process which can actually mock the response coming in (in encoded format) from the API call, and then I decode that object. 是否有一个requests.content.encode('utf-8',data))看起来类似的过程,该过程实际上可以模拟来自API调用(以编码格式)的响应,然后我对该对象进行解码。

sample code: 样例代码:

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 

So for instance, if I wanted to unit test the get_something function, I need to mock the sample_fct function. 因此,例如,如果要对get_something函数进行单元测试,则需要模拟sample_fct函数。 to do this, i would have to set the sample_fct.return_value to a request object that it is returning. 为此,我将必须将sample_fct.return_value设置为其返回的请求对象。

So how do I create that object. 那么如何创建该对象。

Here's how you can mock the response like I was saying above. 像我上面所说的那样,您可以按照以下方法模拟响应。 Note that I took some liberties to make your code and my test actually work. 请注意,我采取了一些自由措施来使您的代码和我的测试真正起作用。 They are included in comments: 它们包含在注释中:

"""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 

You can see in the test how I assign the return value of your mocked sample_fct to an arbitrary Mock object. 您可以在测试中看到如何将Mock sample_fct的返回值分配给任意的Mock对象。 That object can have arbitrary attributes assigned to it, which can aid in testing for return values that may be many attribute levels deep. 可以为该对象分配任意属性,这可以帮助测试可能具有许多属性级别的返回值。

"""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)

Note that you can also assign attributes of attributes on a Mock . 请注意,您还可以在Mock上分配属性的属性。 So if your caller is expecting something like request.attributes.nested_attributes.value , you could do something like this and Mock will allow it: 因此,如果您的呼叫者期望的是诸如request.attributes.nested_attributes.value东西,则可以执行以下操作,而Mock会允许它:

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

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

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