Charles
Charles

Reputation: 1153

Python mocked exception not being caught

Struggling to succinctly describe this in the title...

I have a module I want to test:

mod.py:

import subprocess
class MyStuff(object):
    def my_fun(self):
        try:
            print subprocess
            out = subprocess.check_output(["echo", "pirates"])
        except subprocess.CalledProcessError:
            print "caught exception"

And the test module test_mod.py:

import unittest
import mock
from mod import MyStuff
import subprocess

class Tests(unittest.TestCase):
    def setUp(self):
        self.patched_subprocess = mock.patch(
            'mod.subprocess', autospec=True)
        self.mock_subprocess = self.patched_subprocess.start()
        self.my_stuff = MyStuff()

    def tearDown(self):
        self.patched_subprocess.stop()

    def test_my_fun(self):
        self.mock_subprocess.check_output = mock.Mock(
            side_effect=subprocess.CalledProcessError(0, "hi", "no"))
        with self.assertRaises(subprocess.CalledProcessError):
            out = self.my_stuff.my_fun()

if __name__ == '__main__':
    unittest.main()

I then run python test_mod.py and I see the following output:

<NonCallableMagicMock name='subprocess' spec='module' id='140654009377872'>
.
----------------------------------------------------------------------
Ran 1 test in 0.007s

OK

I'm pleased that the subprocess object has been mocked, but why is the print "caught exception" statement not executed? I'm guessing it's because the real exception getting throw in test_mod.subprocess.CalledProcessException and not subprocess.CalledProcessException as I intend, but I'm not sure how to resolve that. Any suggestion? Thanks for your time.

Upvotes: 2

Views: 1019

Answers (1)

Charles
Charles

Reputation: 1153

I solved this eventually...

The problem was I was mocking the entire subprocess module, which included the CalledProcessError exception! That's why it didn't seem to match the exception I was raising in my test module, because it was a completely different object.

The fix is to mock just subprocess.check_output, D'oh!

Upvotes: 2

Related Questions