4

I have a code like this:

def extract(data):
    if len(data) == 3:
       a = 3
    else:
        component = data.split("-")
        if len(component) == 3:
            a,b,c = component
        else:
            raise globals.myException("data1", "Incorrect format", data)

    return a,b,c

This is a simplified one. I want to mock the exception class globals.myException. I'm doing that:

def test_extract_data_throws_exception(self):
        with patch('globals.myException') as mock: 
            mock.__init__("data1", "Incorrect format", "")
            with self.assertRaises(myException):
                self.assertEqual(extract(""), (""))

And I always get the error: "TypeError: exceptions must be old-style classes or derived from BaseException, not MagicMock"

EDIT: As @Aaron Digulla suggest, monkey patching is the correct solution. I post the solution to help others.

def test_extract_data_throws_exception(self):
        #monkey patching
        class ReplaceClass(myException):
            def __init__(self, module, message, detail = u''):
                pass

        globals.myException = ReplaceClass
        with self.assertRaises(myException:
            self.assertEqual(extract(""), (""))
Killrazor
  • 6,856
  • 15
  • 53
  • 69
  • Why do you want to mock the exception? Why not simply throw it and catch it in the test? – Aaron Digulla Feb 08 '13 at 11:05
  • 1
    MyException extends from Exception but adding some funcionality as Log services and other things. I know that I could include my exception as part of my test but I'd like to keep clean my unit test. Also, it is a matter of curiosity :) – Killrazor Feb 08 '13 at 11:09

1 Answers1

4

The reason is raise checks the type of the argument. It must be a string (a.k.a "old style exceptions") or derived from BaseException

Since a mock isn't either, raise refuses to use it.

In this specific case, you either have to raise the exception or use monkey patching (= overwrite the symbol globals.myException in your test and restore it afterwards).

Community
  • 1
  • 1
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820