python - How do I patch a class in the same file as a class under test, that is initialized before the test begins? -
(nota bene: heavily modified original question, include details erroneously elided.)
this (summarized) file (common.py) i'm testing. contains decorator (derived decorum library) calls class method on object(a): want patch out a, because code makes external call i'm not testing.
from decorum import decorum class a: @classmethod def c(cls): pass class classydecorum(decorum): """hack allow decorated instance methods of class object run decorators. replace once decorum 1.0.4+ comes out. """ def __get__(self, instance, owner): functools import partial return partial(self.call, instance) class b(decorum): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def init(self, *args, **kwargs): a.c() return super().init(*args, **kwargs) i'd @patch class a in unittest, isolate , check b.d()'s functionality. unittest (located in test/test_common.py):
class bdecoratedclass(magicmock): @b def dummy_func(self): return "success" class testb(testcase): @patch('unittest_experiment.a', autospec=true) def test_d(self, mock_a): b = bdecoratedclass() b.dummy_func() mock_a.c.assert_called_once_with() # fails debugging above, see a never mocked: code proceeds a's code, makes sense mock_a never called, , assertion fails. however, i'd monkey patch a. approach works if i'm monkey patching import exists in common.py, apparently not if class defined there?
note think issue of where i'm patching, @patch('common.a', autospec=true) should more @patch('where.python.actually.finds.a.when.b.calls.a', autospec=true). i'm unclear on how determine if case, , if so, correct path is. instance, @patch('bdecorated.common.a', autospec=true) not work.
thanks @user2357112, arrived @ solution. caveat: don't know if standard or 'best' practice, seems work.
first, move bdecoratedclass it's own file in test/dummy.py. change test this:
class testb(testcase): @patch('common.a', autospec=true) def test_d(self, mock_a): test.dummy import bdecoratedclass b = bdecoratedclass() b.dummy_func() mock_a.c.assert_called_once_with() # succeeds this forces patch execute prior import of dummy class being decorated. it's little weird because import inside function, test seems fine.
bigger caveat:
this works first test imports module where, in case bdecoratedclass imports from. @ juncture else in class has been loaded , cannot patched.
Comments
Post a Comment