Python 如何模拟一个类';s函数';返回值是多少?

Python 如何模拟一个类';s函数';返回值是多少?,python,unit-testing,Python,Unit Testing,我在Python中有一个类似这样的方法(在comicfile.py中): 我正试图为此编写一个单元测试(我已经测试了prune\u dirs),因此我就有了(test\u comicfile.py): 当我运行此测试时,我得到以下结果: F..ss.... ====================================================================== FAIL: test_page_count (test_comicfile.TestPageCoun

我在Python中有一个类似这样的方法(在
comicfile.py
中):

我正试图为此编写一个单元测试(我已经测试了
prune\u dirs
),因此我就有了(
test\u comicfile.py
):

当我运行此测试时,我得到以下结果:

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)
好的,
self.comic\u file.page\u count()
正在返回
0
。我尝试在
page\u count
中的
members=zip.namelist()
之后放置以下行

print('\nmembers -> ' + str(members))
在测试过程中,我得到以下信息:

members -> <MagicMock name='ZipFile().__enter__().namelist()' id='4483358280'>
成员->
我对单元测试非常陌生,对使用
unittest.mock
非常模糊,但我的理解是
mock\u zip-file.return\u value.namelist=list(file\u tuple)
应该这样做,
ZipFile
类的
namelist
方法将依次返回每个
文件组的内容。我不知道它在干什么


我想我在这里要做的很清楚,但是我似乎不知道如何覆盖
名称列表
方法,这样我的单元测试就只测试这一个函数,而不必处理
ZipFile

ZipFile
被实例化为一个函数。对于它,您必须参考其
\uuu\uu enter\uu
方法

mock\u zip\u file.return\u value.\uu\u输入\uuuu.return\u value.namelist.return\u value=list(file\u tuple)

您试图做的是非常清楚的,但是上下文管理器增加了模拟的复杂性


一个技巧是,当一个mock注册对它的所有调用时,在本例中,它表示它在以下位置有一个调用:

成员->


这可以指导您注册模拟对象,将所有
()
替换为
返回值

您的代码很混乱。“ComicFile”和“ComicFile”是1类(一旦拼写错误)还是2类?第一个代码段中的“Zipfile”应该是“self.Zipfile”吗?在不知道细节的情况下,我想知道你是否需要模拟。每个测试都应该假设其他一切都正常。只有当测试失败时,你才会质疑这一点。需要有一个积极的理由来嘲笑某些事情。例如,“调用将在测试设置中失败”或“调用真实对象需要太多的时间或空间”或“返回不确定”。很可能我使用的是非python命名约定,尽管我试图遵守这些约定
ComicFile
是类,
ComicFile
是包含类的模块<代码>ZipFile
通过
从ZipFile导入ZipeFile
导入。我想我需要模拟,因为如果我不这样做,为了测试这个,我实际上需要在文件系统中有zip文件,我只想测试一下,如果zip文件对象返回一个
名称列表
,这个函数会正确计算文件数。模拟很混乱,特别是关于上下文管理器。模仿外部资源是一个很好的用途。如果我没有将其用作上下文管理器,并且只进行一次函数调用,我可能会临时将Zipfile替换为“class Zipfile:\n def namelist():return…”。但是对于这个例子,我也从dm03514的伟大答案中学到了一些东西。我复制、粘贴并让测试开始工作,我在整个代码中放置的打印图显示了我期望他们做的事情(模拟成员)。当然,我还不明白它为什么会起作用,这会让我感到困扰,直到我弄明白为止。我已经阅读了几次
mock
文档,但我会看看你链接的文章,也许这会帮助我理解那种代码的含义。我(想)我现在明白了。如果我设置
zip
而不使用
块,但只使用
zip=ZipFile…
,那么
mock\u-zip\u-file.return\u-value.namelist.return\u-value=list(file\u-tuple)
就可以工作了。您引用的
打印
中的
\uuu\uu输入
应该会提醒我,我用于获取
名称值
的路径不正确。
print('\nmembers -> ' + str(members))
members -> <MagicMock name='ZipFile().__enter__().namelist()' id='4483358280'>