1

Consider the following:

Class:

class Something(object):
    def should_not_be_called(self):
        pass

    def should_be_called(self):
        pass

    def do_stuff(self):
        self.should_be_called()
        try:
            self.should_not_be_called()
        except Exception:
            pass

Unit test:

class TestSomething(unittest.TestCase):
    def test(self):
        mocker = mox.Mox()

        something = Something()
        mocker.StubOutWithMock(something, 'should_be_called')
        mocker.StubOutWithMock(something, 'should_not_be_called')

        something.should_be_called()

        mocker.ReplayAll()

        something.do_stuff()

        mocker.VerifyAll()

This test will pass (when it should clearly fail) as the try..except in do_stuff() will except the UnexpectedMethodCallError while the test runs...

Is there a way to get around this?

Edit: Another example that exemplifies why this is a problem a bit better:

class AnotherThing(object):
    def more_stuff()(self, num):
        if i == 2:
            raise ValueError()

    def do_stuff(self):
        for i in [1, 2, 3, 'boo']:
            try:
                self.more_stuff(i)
            except Exception:
                logging.warn("an exception might have been thrown but code should continue")


class TestAnotherThing(unittest.TestCase):
    def test(self):
        mocker = mox.Mox()

        another_thing = Something()
        mocker.StubOutWithMock(something, 'fails_on_2')
        mocker.StubOutWithMock(something, 'called_when_no_error')

        another_thing.more_stuff(1)
        # actual function calls more_stuff 2 more times, but test will still pass 
        another_thing.more_stuff('boo')

        mocker.ReplayAll()

        another_thing.do_stuff()

        mocker.VerifyAll()
pseudoDust
  • 1,336
  • 1
  • 10
  • 18
  • Out of curiosity, if you are using Python 3, why not use the provided [mock](https://docs.python.org/3/library/unittest.mock.html) – idjaw Oct 15 '17 at 13:17
  • 1
    You're catching the exception, so your code will never raise anything. What is your expectation in the test? Also, you seem to not specify anywhere in your test to raise anything for the except to *catch* anything. – idjaw Oct 15 '17 at 13:20
  • I'm on python 2 :( I expect the test to fail as a method that should not be called, is called... the example is obviously simplified, the actual code I'm testing can raise a variety of exceptions... – pseudoDust Oct 15 '17 at 13:32
  • I've never used `mox`. But, in `mock` you have to explicitly state that your mocked method (in this case `should_not_be_called`) should raise an exception. For example, in mock you would do something like: `mock_should_not_be_called.side_effect = SomeException`. – idjaw Oct 15 '17 at 13:34
  • So, when you call the `do_stuff` method, the mocked out method will now raise and you will catch it, meeting your exception handling case for your test. You would have to determine how to do this in the `mox` equivalent. However, you can install `mock` in python 2 FYI. [mock](https://pypi.python.org/pypi/mock) – idjaw Oct 15 '17 at 13:35
  • Mox has that functionality as well, but I'm not trying to test the handling of exceptions, I want the test to fail because `should_not_be_called` should not be called, and it is... it does not throw an exception, mox does, as it should. but the mox exception (that should fail the test) is caught by the try in the code. I've added a more detailed example, hope it helps. – pseudoDust Oct 15 '17 at 14:15

0 Answers0