11

Given this Python code:

elif request.method == 'DELETE':
    try:
        os.remove(full_file)
        return jsonify({'results':'purged %s' % full_file})

    except OSError as e:
        if e.errno != errno.ENOENT:
            raise

        return jsonify({'results':'file not present: %s' % full_file})

I want to test all possible paths, including the exception handling. Using Mock, it's easy enough to raise an exception, which I do with this code:

with patch('os.remove', new=Mock(side_effect=OSError(errno.ENOENT))):
    self.assertRaises(OSError, self.app.delete, file_URL) # broken

Mock raises an exception, which has a printed value of 2 (ENOENT) - but e.errno is set to NONE. And so far, I have not found a way to set it. The result is, the exception always gets re-raised, and I never reach the last line of code, in my unit test.

I've also tried creating a dummy class with errno set, and returning that. But unless it has *side_effect* set to be called, it doesn't raise an exception, and when I set side_effect, I don't get the object.errno as a return value.

Is there a way to have Mock raise an Exception, where that Exception object has the errno attribute set?

John C
  • 6,285
  • 12
  • 45
  • 69

1 Answers1

11

Pass two arguments to OSError constructor. (First one should be errno).

For example:

>>> OSError(2).errno
>>> OSError(2, 'message').errno
2
>>> OSError(2, 'message').strerror
'message'
falsetru
  • 357,413
  • 63
  • 732
  • 636
  • 1
    Wow, that was fast - and correct. :) Was this somewhere in Python's Exception docs? I did read those, but may have missed something. – John C Dec 12 '13 at 15:18
  • @JohnC, I raised OSError intentionally and checked `args` attribute of the exception object. – falsetru Dec 12 '13 at 15:24
  • Interesting - how did you determine that one of the `args` was `errno`? I'm looking at it, it just seems to be a tuple. – John C Dec 12 '13 at 15:30
  • @JohnC, `args` is a tuple of arguments passed to the exception constructor. – falsetru Dec 12 '13 at 15:34
  • @JohnC, See [`args` from exceptions module documentation](http://docs.python.org/2/library/exceptions.html#exceptions.BaseException.args) – falsetru Dec 12 '13 at 15:34
  • Ah, I was looking at OSError, and should have followed it up to [EnvironmentError](http://docs.python.org/2/library/exceptions.html#exceptions.EnvironmentError), where they explain `errno` in more detail. Thanks, this was a learning experience. – John C Dec 12 '13 at 15:40