I wanted to test a method on a class that didn't really depend on a lot of other stuff off the class. Or rather what it did depend on I had already turned into Mock objects with appropriate .return_value and asserting with .called etc. Problem was that the .__init__() method of the object invoked about half the application framework (option parsing, configuration file loading, setting up logging etc.). Firstly I don't really feel like testing all of that (hey, these are called unittests after all and those fuctionalities have their own!) and secondly then I had to worry about way too much, quite a lot to setup.
That's how the whacky idea of replacing the .__init__() method with a mock occurred to me:
class TestSomething(object): @mock.patch('module.Klass.__init__', mock.Mock(return_value=None)) def test_method(self): inst = module.Klass() inst.other_method = mock.Mock() inst._Klass__log = mock.Mock() # more of this inst.method() assert inst.other_method.called
The ugly side effects of deciding to mock away the .__init__() method like this is that I have to create mocks for more internal stuff. The one shown for exampls is normally provided by self.__log = logging.getLogger('foo').
I must admit that I'm still trying to find my way in how to use the Mock module effectively and hence I'm not really sure how sane this approach is. One of my objections with this is that not only am I meddling with clearly hidden attributes of the class, but I also have to do this again and again for each test method. So the next revision (I'm using py.test as testing framework here btw):
class TestSomething(object): @classmethod def setup_class(cls): cls._original_init_method = module.Klass.__init__ module.Klass.__init__ = mock.Mock(return_value=None) @classmethod def teardown_class(cls): module.Klass.__init__ = cls._original_init_method def setup_method(self, method): self.inst = module.Klass() self.inst._Klass__log = mock.Mock() # more of this def test_method(self): self.inst.other_method = mock.Mock() self.app.method() assert self.inst.other_method.called
This is actually workable and I'm testing what I want to test in a pretty isolated way. I'm still wondering whether I've gone insane or not tough. Is it reasonable to replace .__init__() by mock objects? Have other people done this?