简体   繁体   中英

Mock patch method and an attribute

I would like to patch an attribute of the data returned by a method.

Assuming I have the following simplified piece code:

@patch('requests.post')
class TestKeywordsApi(BaseTest):
    # Instantiate API class and set the apikey
    def setUp(self):
        BaseTest.setUp(self)
        self.fixtures = FIXTURES
        self.api = BaseApi()

    def mock_requests_post(self, url, data=None):
        ''' Mock method for post method from responses library.
            It replaces the responses.post calls in Api class.
        '''
        url = self.encode_url(url, data)
        if url:
            return self.fixtures[url]

    def test_save_success(self, mock_post):
        mock_post.side_effect = self.mock_requests_post

        response = self.api.post(keyword, params={...})

        # list of asserts

# original class calling requests.post    
import requests
class BaseApi(object):
    def post(self, action, params):
        ''' Sends a POST request to API '''
        response = requests.post(self.build_url(action), data=params).content

The code above fails because the mock method does not provide a mock/stub for 'content' attribute present in requests library. Does anyone know how to stub the content attribute?

your mocked post function needs to return an object that is more like requests 's response objects, one that has a .content attribute. eg:

from mock import Mock, patch
#[...]
def mock_requests_post(self, url, data=None):
    ''' Mock method for post method from responses library.
        It replaces the responses.post calls in Api class.
    '''
    mock_response = Mock()
    mock_response.content = 'my test response content'
    url = self.encode_url(url, data)
    if url:
        mock_response.url_called = self.fixtures[url]
    return mock_response

I found the following solution, which only modifies the mock_requests_post method, adding an internal class with the attribute that I need:

def mock_requests_post(self, url, data=None):
    ''' Mock method for post method from responses library.
        It replaces the responses.post calls in Api class.
    '''
    url = self.encode_url(url, data)

    class classWithAttributes(object):
        content = json.dumps(self.fixtures[url])

    if url:
        return classWithAttributes()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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