Search code examples
pythonpython-requestspython-unittest

How to mock a http request post in python unittest


First time write unittest. Production code:

def get_session_token(organization_id):
    endpoint = get_endpoint(organization_id)
    response = requests.post(
        endpoint + "/some/url/part",
        data=json.dumps({
            "Login": CONFIG[organization_id]["username"],
            "Password": CONFIG[organization_id]["password"],
        }),
        headers={"Accept": "application/json"}
    )

    if response.status_code != 201:
        log.error("filename.get_session_token(%r): couldn't auth: %r %r",
                  organization_id, response, response.text)
        raise ValueError()

    return response.json()

def member(organization_id):
    session_key = get_session_token(organization_id)
    (some other code...)

I need to test member. And I have test code:

@patch('requests.post')
def test_member(self, mock_post):
    mock_post().status_code = 201
    mock_response = mock_post("some/url", data=ANY,
                              headers={"Accept": "application/json"})
    mock_response.status_code = 201
    (some other code...)

Every time I run test, it always raises ValueError()(which is a 403 error)

How can I bypass that requests.post and just get a 201?

Thank you!


Solution

  • See Where to patch. And, you should provide a mock return value for the mock_post using return_value - The value returned when the mock is called.

    E.g.

    member.py:

    import requests
    import json
    
    
    def get_session_token(organization_id):
        endpoint = 'http://localhost:3000/api'
        response = requests.post(
            endpoint + "/some/url/part",
            data=json.dumps({
                "Login": 'python',
                "Password": '123456',
            }),
            headers={"Accept": "application/json"}
        )
        if response.status_code != 201:
            raise ValueError()
    
        return response.json()
    
    
    def member(organization_id):
        session_key = get_session_token(organization_id)
        return session_key
    

    test_member.py:

    from unittest.mock import patch
    import unittest
    import json
    from member import member
    
    
    class TestMember(unittest.TestCase):
        @patch('member.requests.post')
        def test_member_success(self, mock_post):
            mock_post.return_value.status_code = 201
            mock_post.return_value.json.return_value = 'mock response'
    
            actual = member(1)
            self.assertEqual(actual, 'mock response')
            mock_post.assert_called_once_with(
                'http://localhost:3000/api/some/url/part',
                data=json.dumps({
                    "Login": 'python',
                    "Password": '123456',
                }),
                headers={"Accept": "application/json"}
            )
    
        @patch('member.requests.post')
        def test_member_failure(self, mock_post):
            mock_post.return_value.status_code = 400
            self.assertRaises(ValueError, member, 1)
    
    
    if __name__ == '__main__':
        unittest.main()
    

    Test result:

    .
    ----------------------------------------------------------------------
    Ran 1 test in 0.001s
    
    OK
    Name                                        Stmts   Miss  Cover   Missing
    -------------------------------------------------------------------------
    src/stackoverflow/70098351/member.py           11      2    82%   18, 23
    src/stackoverflow/70098351/test_member.py      11      0   100%
    -------------------------------------------------------------------------
    TOTAL                                          22      2    91%