Search code examples
pythonunit-testingpatch

unittest class init mock exception raised


#!/usr/bin/env python3

import unittest
from unittest.mock import patch

class User(object):
    def __init__(self):
        self.__name = None
        self.__authorised_users = ["me", "you"]
        local_input = input("please provide your windows 8 character lower case login: ")
        if local_input not in self.__authorised_users:
            raise ValueError("you have no permission to run this app")
        else:
            self.__name = local_input

class TestUser(unittest.TestCase):
    def testUserClassFound(self):
        self.assertNotIsInstance(ModuleNotFoundError, User)
    @patch('builtins.input', lambda *args:"y")
    def testUserClassInit(self): # just check if user class has __name set to none
        local_object = User()
        self.assertEqual(local_object._User__name, None)

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

I would like to, in the second test, just assure when the class object is created, the tester checks the class has the attribute __name and set to None. I need to patch the raise ValueError from the class init , but I can't find the correct patch.


Solution

  • You can patch User.__init__ with a wrapper that suppresses ValueError:

    def ignore(func, exception):
        def wrapper(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except exception:
                pass
        return wrapper
    
    class TestUser(unittest.TestCase):
        @patch('builtins.input', lambda *args:"y")
        @patch.object(User, '__init__', ignore(User.__init__, ValueError))
        def testUserClassInit(self):
            local_object = User()
            self.assertEqual(local_object._User__name, None)
    

    Demo: https://ideone.com/TEpHsF