Search code examples
pythonpython-unittestpython-mock

How to stop execution of python program using mock?


I'm using unittest and mock for testing a script which looks like this

class Hi:
    def call_other(self):
       perform some operation
       sys.exit(1)


    def f(self):
       try:
           res = self.do_something()
           a = self.something_else(res)
       except Exception as e:
           print(e)
           call_other()

       print("hi after doing something")  -----> (this_print)


    def process(self)
       self.f()

and my test script looks like this

    class Test_hi(unittest.TestCase)
        def mock_call_other(self):
            print("called during error")

        def test_fail_scenario():
           import Hi class here
           h = Hi()
           h.process()
           h.do_something = mock.Mock(retrun_value="resource")
           h.something_else = mock.Mock(side_effect=Exception('failing on purpose for testing'))
           h.call_other(side_effect=self.mock_call_other)   -----> (this_line)

If I don't mock call_other method it will call sys.exit(1) and it will cause some problem in unittest running, so, I don't want to call sys.exit(1) in call_other during testing. However, if I mock call_other method as above (in this_line) it will simply print something and continue the execution of method f. Meaning, it will execute the print statement (in this_print) That should not be the case in the real program, when the exception is caught it will do a sys.exit(1) and stop the program. How can I achieve the same using unittest and mock when the exception is caught I want to stop the execution of this testcase and move on to next test case.

How to achieve this? Please help


Solution

  • You can use unittest's functionality to assert if you're expecting exceptions without the need of mock:

    import unittest
    import sys
    
    
    class ToTest:
        def foo(self):
            raise SystemExit(1)
    
        def bar(self):
            sys.exit(1)
    
        def foo_bar(self):
            print("This is okay")
            return 0
    
    class Test(unittest.TestCase):
        def test_1(self):
            with self.assertRaises(SystemExit) as cm:
                ToTest().foo()
    
            self.assertEqual(cm.exception.code, 1)
    
        def test_2(self):
            with self.assertRaises(SystemExit) as cm:
                ToTest().bar()
    
            self.assertEqual(cm.exception.code, 1)
    
        def test_3(self):
            self.assertEqual(ToTest().foo_bar(), 0)