0

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)
qkslvrwolf
  • 179
  • 2
  • 10
  • Show us how you're patching it now and how that property is imported - the latter being very important to figuring out where to patch. – Makoto Apr 28 '15 at 17:15
  • Added the info to the main. – qkslvrwolf Apr 28 '15 at 17:46
  • Thanks for that, this adds a bit more to the puzzle. Last bit: you say that `Lunabuild` lives in that file structure. Where are you invoking it? Is it in the same module? – Makoto Apr 28 '15 at 17:48

1 Answers1

1

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:

  1. It is more complicated to understand what you are doing
  2. To use it you should know more about objects to patch the right things
Michele d'Amico
  • 22,111
  • 8
  • 69
  • 76