I have a package that looks like this:
lcl
|
| - lcl
| - LCL.py
| - lunabuild.py
In the lunabuild module, there is a Lunabuild class. The Lunabuild class has a method Lunabuild.configure_jobs(). The LCL class imports lunabuild:
from lcl import lunabuild
It then uses it as a lazily instantiated property:
@property
def luna_build(self):
self._luna_build = lunabuild.Lunabuild()
the LCL class has a main() method that runs the Lunabuild.configure_jobs() method:
main(self)
try:
self.luna_build.configure_jobs()
except ValidationError:
...
except Exception, e:
return_code = 2
self.logger_exception(e)
I'm trying to patch configure_jobs to have a side_effect that raises an error, so that I can test that unknown errors are logged as expected.
I have been unable to figure out where to patch. it keeps telling me that it doesn't recognize the attribute, or that lunabuild has no configure_jobs attribute.
I've tried a bunch of different options. Running with a debugger attached, I can see that test_lcl in the following code is an lcl.lunabuild.Lunabuild object
UPDATE: my latest attempt is
with patch.object('lcl.lunabuild.Lunabuild', 'configure_jobs') as mock:
mock.side_effect = OSError(2, 'message')
retcode = test_lcl.main()
self.assertEquals(retcode, 2)
The simpler way to do it is to path the static reference of configure_jobs
method in Lunabuild
class definition. So use follow code should do exactly what you need
with patch('lcl.lunabuild.Lunabuild.configure_jobs', side_effect=OSError(2, 'message')) as mock:
retcode = test_lcl.main()
self.assertEquals(retcode, 2)
If you want patch just the object that you use in your test you can do it by:
with patch.object(test_lcl.luna_build, 'configure_jobs', side_effect = OSError(2, 'message')) as mock:
retcode = test_lcl.main()
self.assertEquals(retcode, 2)
My taste is to use patch.object
just when I have no other chance: