dimanche 24 juillet 2016

How do I mock ZipFile's namelist?

I have a method in Python that looks like this:

def page_count(self):
    """Return the number of pages in the file."""
    if self.file == None:
        raise ComicFile.FileNoneError()

    if not os.path.isfile(self.file):
        raise ComicFile.FileNotFoundError()

    with ZipFile(self.file) as zip:
        members = zip.namelist()
        pruned = self.prune_dirs(members)
        length = len(pruned)
        return length

I'm trying to write a unit test for this (I've already tested prune_dirs), and so for this is what I have:

@unittest.mock.patch('comicfile.ZipFile')
def test_page_count(self, mock_zip_file):
    # Store as tuples to use as dictionary keys.
    members_dict = {('dir/', 'dir/file1', 'dir/file2'):2,
                    ('file1.jpg', 'file2.jpg', 'file3.jpg'):3
    }

    # Make the file point to something to prevent FileNoneError.
    self.comic_file.file = __file__

    for file_tuple, count in members_dict.items():
        mock_zip_file.return_value.namelist = list(file_tuple)
        self.assertEqual(count, self.comic_file.page_count())

When I run this test, I get the following:

F..ss....
======================================================================
FAIL: test_page_count (test_comicfile.TestPageCount)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/unittest/mock.py", line 1157, in patched
    return func(*args, **keywargs)
  File "/Users/chuck/Dropbox/Projects/chiv/chiv.cbstar/test_comicfile.py", line 86, in test_page_count
    self.assertEqual(count, self.comic_file.page_count())
AssertionError: 2 != 0

----------------------------------------------------------------------
Ran 9 tests in 0.010s

FAILED (failures=1, skipped=2)

OK, so self.comic_file.page_count() is returning 0. I tried placing the following line after members = zip.namelist() in page_count.

print('\nmembers -> ' + str(members))

During the test, I get this:

members -> <MagicMock name='ZipFile().__enter__().namelist()' id='4483358280'>

I'm quite new to unit testing and am quite nebulous on using unittest.mock, but my understanding is that mock_zip-file.return_value.namelist = list(file_tuple) should have made it so that the namelist method of the ZipFile class would return each of the file_tuple contents in turn. What it is doing I have no idea.

I think what I'm trying to do here is clear, but I can't seem to figure out how to override the namelist method so that my unit test is only testing this one function instead of having to deal with ZipFile as well.

Aucun commentaire:

Enregistrer un commentaire