Mocking Urllib3. Poolmanager(). Request Function with Python

Mocking Urllib3. Poolmanager(). Request Function with Python

I have a function that makes a POST request using urllib3.PoolManager(). Now in the unit test I want to mock said request but having some difficulty. What's the correct way to do it?

My code:

http = urllib3.PoolManager()
# my func
def func(event, context):
    ...
    resp = http.request('POST', url, body=encoded_msg)
    ...

# unit test
@patch('urllib3.PoolManager.request')
def test_lambda_handler(self, mock_instance):
    mock_instance.return_value = Mock(status = "200", data = "success")
    res = func(event, [])
    mock_instance.request.assert_called_once()

I get this error "AssertionError: Expected 'request' to have been called once. Called 0 times."

1 Answer

Since you call the constructor of the urllib3.PoolManager class in global (or module) scope. Reference: #where-to-patch

module b does import a and some_function uses a.SomeClass. ... In this case the class we want to patch is being looked up in the module and so we have to patch a.SomeClass instead: @patch('a.SomeClass')

Option 1: import the func after mocking urllib3.PoolManager class

lambda_handler.py:

import urllib3
import json

http = urllib3.PoolManager()
print('http: ', http)

def func(event, context):
    url = '
    data = {'attribute': 'value'}
    encoded_msg = json.dumps(data).encode('utf-8')
    resp = http.request('POST', url, body=encoded_msg)

test_lambda_handler.py:

import unittest
import json
from unittest import mock


class TestLambdaHandler(unittest.TestCase):

    @mock.patch('urllib3.PoolManager')
    def test_lambda_handler(self, mock_PoolManager):
        from lambda_handler import func
        mock_http = mock_PoolManager.return_value
        event = {}
        func(event, [])
        mock_http.request.assert_called_once_with('POST', ' body=json.dumps({'attribute': 'value'}).encode('utf-8'))


unittest.main(verbosity=2)

test result:

test_lambda_handler (__main__.TestLambdaHandler) ... http:  <MagicMock name='PoolManager()' id='4475122928'>
ok

----------------------------------------------------------------------
Ran 1 test in 0.063s

OK
Name                                                Stmts   Miss  Cover   Missing
---------------------------------------------------------------------------------
src/stackoverflow/69890084/lambda_handler.py            9      0   100%
src/stackoverflow/69890084/test_lambda_handler.py      12      0   100%
---------------------------------------------------------------------------------
TOTAL                                                  21      0   100%

Option 2: mock the global variable http, you don't need to import the func after mocking

If you import the lambda_handler module at the top of the test file, the module lambda_handler will have a reference to the real urllib3.PoolManager so that it's too late for mocking.

import unittest
import json
from unittest import mock
from lambda_handler import func


class TestLambdaHandler(unittest.TestCase):
    @mock.patch('lambda_handler.http')
    def test_lambda_handler(self, mock_http):
        event = {}
        func(event, [])
        mock_http.request.assert_called_once_with('POST', ' body=json.dumps({'attribute': 'value'}).encode('utf-8'))


unittest.main(verbosity=2)

test result:

http:  <urllib3.poolmanager.PoolManager object at 0x1104b2610>
test_lambda_handler (__main__.TestLambdaHandler) ... ok

----------------------------------------------------------------------
Ran 1 test in 0.002s

OK
Name                                                Stmts   Miss  Cover   Missing
---------------------------------------------------------------------------------
src/stackoverflow/69890084/lambda_handler.py            9      0   100%
src/stackoverflow/69890084/test_lambda_handler.py      11      0   100%
---------------------------------------------------------------------------------
TOTAL                                                  20      0   100%

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Marcus Vance
Author

Marcus Vance

Marcus Vance is a cybersecurity auditor and technology writer dedicated to educating the public about online safety, data privacy regulations, enterprise security, and emerging cyber threats.