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

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

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.

You Might Also Like