Модульный тест Python, как использовать Mox, чтобы высмеивать gzip с оператором - PullRequest
1 голос
/ 18 января 2012

Как в Python смоделировать объект, созданный в операторе with, с помощью библиотеки модульного теста mox

Код

class MyCode:
    def generate_gzip_file(self):
        with gzip.GzipFile('file_name.txt.gz','wb') as f:
             f.write('data')

Модульный тест

class MyCodeTest(unittest.TestCase):
    def test_generate_gzip_file(self):
        mox = mox.Mox()
        mock_gzip_file = self.mox.CreateMock(gzip.GzipFile)
        mox.StubOutWithMock(gzip, 'GzipFile')
        gzip.GzipFile('file_name.txt.gz','wb').AndReturn(mock_file)
        mock_gzip_file.write('data')
        mox.ReplayAll()
        MyCode().generate_gzip_file()
        mox.VerifyAll()

Я получаю ошибку AttributeError: __exit__ в строке

with gzip.GzipFile('file_name.txt.gz','wb') as f:

1 Ответ

3 голосов
/ 19 января 2012

DSM верен, что по какой-то причине максимизированный экземпляр gzip.GzipFile не заканчивается методом __exit__. Вы получите точно такую ​​же ошибку, если забудете определить __exit__ для класса, который вы используете с помощью оператора with. Например:

>>> class C(object):
...   def __enter__(self):
...     return self
... 
>>> with C() as c:
...   pass
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: __exit__

К счастью, вы можете обойти эту проблему, используя метод CreateMockAnything() Mox для создания mock_gzip_file объекта, который не обеспечивает конкретного интерфейса. Вы должны быть осторожны, чтобы убедиться, что вы правильно настроили ожидания для объекта mock_gzip_file (то есть, чтобы вы установили ожидания относительно того, когда и как будут вызываться методы __enter__() и __exit__(...)). Вот пример, который работал для меня:

import gzip
import mox
import unittest

class MyCode:
    def generate_gzip_file(self):
        with gzip.GzipFile('file_name.txt.gz', 'wb') as f:
             f.write('data')

class MyCodeTest(unittest.TestCase):
    def test_generate_gzip_file(self):
        mymox = mox.Mox()
        mock_gzip_file = mymox.CreateMockAnything()
        mymox.StubOutWithMock(gzip, 'GzipFile')
        gzip.GzipFile('file_name.txt.gz', 'wb').AndReturn(mock_gzip_file)
        mock_gzip_file.__enter__().AndReturn(mock_gzip_file)
        mock_gzip_file.write('data')
        mock_gzip_file.__exit__(None, None, None).AndReturn(None)
        mymox.ReplayAll()

        MyCode().generate_gzip_file()
        mymox.VerifyAll()

if __name__ == '__main__':
    unittest.main()

Когда я запускаю это, я получаю:

.
----------------------------------------------------------------------
Ran 1 test in 0.001s

OK
...