2011-03-11

Mocking logging in python

from logging import getLogger, StreamHandler

class DirHandler(object):
    def __init__(self):
        l = getLogger()
        l.addHandler(StreamHandler())
    def process_dir(self):
        l = getLogger()
        l.debug('foo')
        l.info('bar')
        l.warn('baz')

import unittest
from mock import Mock, patch
from logging import RootLogger
target = '%s.getLogger' % __name__
@patch(target)
class TestProcessDir(unittest.TestCase):
 def test_logging(self, mock_getLogger):
  mock_getLogger.return_value = Mock(spec=RootLogger)
  d = DirHandler()
  d.process_dir()
  method_calls = mock_getLogger.return_value.method_calls
  print method_calls
  self.assertEqual(0, len(method_calls))
  self.assertEqual(None, method_calls[0][0])

if __name__ == '__main__':
    unittest.main()
Things to note:
  1. Where you patch is both critical and potentially confusing. I tried patching logging.getLogger, but since it's already imported, that didn't work. If your code under test does from foo import bar, then you need to patch mycode.bar rather than foo.bar.
  2. Giving a spec to Mock proves that your code is at least calling your mock according to it's signature.
  3. mock_logger.method_calls is how to access the method calls. I know it's sad, but it took me a while to figure this one out.

0 comments: