I have been having trouble with Python mock and have been going crazy. I've held off on this question due to fear of down voting for not enough research. I have a cumulative 24 hours over the last week trying to figure out how to get this work and cannot.
I have read numerous examples and have created this one from those. I know mock objects are supposed to be easy to use, but this has taken too long. Now I am out of time.
I am trying to do two simple things here:
1. Override a request.ok status code inside another function
2. Cause an urllib2.HTTPError exception to be thrown
I have distilled these two tasks into the simplest possible example for your convenience:
#ExampleModule.py
import requests
import urllib2
def hello_world():
try:
print "BEGIN TRY"
r = requests.request('GET', "http://127.0.0.1:80")
print r.ok
if r.ok:
print "PATCH 1 FAILED"
else:
print "PATCH 1 SUCCESSFUL"
except urllib2.HTTPError:
print "PATCH 2 SUCCESSFUL"
print "EXCEPTION 2 HIT\n"
else:
print "PATCH 2 FAILED\n"
and
#in TestModule.py
import mock
import ExampleModule
def test_function_try():
with mock.patch('ExampleModule.hello_world') as patched_request:
patched_request.requests.request.ok = False
result = ExampleModule.hello_world()
print result
def test_function_exception():
with mock.patch('ExampleModule.hello_world') as patched_exception:
patched_exception.urllib2.side_effect = HTTPError
result = ExampleModule.hello_world()
print result
test_function_try()
test_function_exception()
A normal call to hello_world() outputs:
BEGIN TRY
True
<Response [200]>
A normal call to test_function_try() outputs:
<MagicMock name='hello_world()' id='70272816'>
#From the "print result" inside test_function_try()
A normal call to test_function_exception() outputs:
<MagicMock name='hello_world()' id='62320016'>
#From the "print result" inside test_function_exception()
Obviously, I am not actually returning anything from hello_world() so it looks like the patched object is the hello_world() function instead of the requests or urllib2 patched modules.
It should be noted that when I try to patch with 'ExampleModule.hello_world.requests' or 'ExampleModule.hello_world.urllib2' I get an error saying they cannot be found in hello_world()
QUESTION SUMMARY
UPDATE
After changing the patch target to the requests.request() function, as per @chepner's suggestion, I receive the following output:
BEGIN TRY
False
PATCH 1 SUCCESSFUL
PATCH 2 FAILED
BEGIN TRY
Traceback (most recent call last):
File "C:\LOCAL\ECLIPSE PROJECTS\MockingTest\TestModule.py", line 44, in <module>
test_function_exception()
File "C:\LOCAL\ECLIPSE PROJECTS\MockingTest\TestModule.py", line 19, in test_function_exception
ExampleModule.hello_world()
File "C:\LOCAL\ECLIPSE PROJECTS\MockingTest\ExampleModule.py", line 12, in hello_world
r = requests.request('GET', "http://127.0.0.1:8080")
File "C:\Python27\lib\site-packages\mock\mock.py", line 1062, in __call__
return _mock_self._mock_call(*args, **kwargs)
File "C:\Python27\lib\site-packages\mock\mock.py", line 1118, in _mock_call
raise effect
TypeError: __init__() takes exactly 6 arguments (1 given)
You can't mock local variables in a function. The thing you want to mock is requests.request
itself, so that when hello_world
calls it, a mock object is returned, rather than actually making an HTTP request.
import mock
import urllib2
import ExampleModule
def test_function_try():
with mock.patch('ExampleModule.requests.request') as patched_request:
patched_request.return_value.ok = False
ExampleModule.hello_world()
def test_function_exception():
with mock.patch('ExampleModule.requests.request') as patched_request:
patched_request.side_effect = urllib2.HTTPError
ExampleModule.hello_world()
test_function_try()
test_function_exception()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With