Is it possible to access "real" objects while mocking a module? What I'm trying to do is mock some function, but throw "real" exceptions, like this:
@mock.patch('my_project.requests')
def test_foo(self, mock_requests):
mock_requests.post = mock.Mock(side_effect=requests.ConnectionError())
thread = CommandThread("command", 3, 2, 0)
thread.run() #this is were I exercise requests.post
self.assert(thread.was_successful is False)
Inside my CommandThread I have a check like
try:
requests.post(url, data=data)
except (requests.ConnectionError, requests.Timeout):
self.was_successful = False
however, my test fails because the exception is not caught inside the try/except block (when I do like except Exception:
it works)
The reason, I think, is simply because I mocked this "namespace" in my test case, so I actually raise my_project.requests.ConnectionError
exception rather than proper, requests.ConnectionError
from original package.
Is it somehow possible to access/throw "real" exceptions?
This is happening because your mock is actually overwriting the entire requests module in your code. Here is how you can debug this:
In your code, add this:
try:
requests.post('', data='')
except (requests.ConnectionError, requests.Timeout):
was_successful = False
except Exception, err:
import pdb
pdb.set_trace()
When you run the test, you will be dropped into the debugger so that you can take a look at what is happening. If we look at what you are catching, this is what we see:
(Pdb) requests.ConnectionError
<MagicMock name='requests.ConnectionError' id='4562438992'>
You are actually catching a mock ConnectionError because your mock patched out the entire requests module and you were feeding in a real requests error.
You can fix this by making your mock more specific and only overriding the post method on the requests module:
@mock.patch('my_project.requests.post')
def test_foo(self, mock_requests):
mock_requests.side_effect = requests.ConnectionError()
...