【问题标题】:AttributeError: __exit__ when I try to mock out build in functionsAttributeError: __exit__ 当我尝试模拟内置函数时
【发布时间】:2014-07-01 14:41:25
【问题描述】:

我目前正在尝试模拟 Python 中的 open() 内置方法进行测试。但是,我总是会遇到崩溃,并且会出现以下消息:

   File "/opt/home/venv/lib/python2.7/site-packages/nose-1.3.0-py2.7.egg/nose/result.py", line 187, in _exc_info_to_string
return _TextTestResult._exc_info_to_string(self, err, test)
 File "/opt/python-2.7.3/lib/python2.7/unittest/result.py", line 164, in _exc_info_to_string
msgLines = traceback.format_exception(exctype, value, tb)
 File "/opt/python-2.7.3/lib/python2.7/traceback.py", line 141, in format_exception
list = list + format_tb(tb, limit)
 File "/opt/python-2.7.3/lib/python2.7/traceback.py", line 76, in format_tb
return format_list(extract_tb(tb, limit))
  File "/opt/python-2.7.3/lib/python2.7/traceback.py", line 101, in extract_tb
line = linecache.getline(filename, lineno, f.f_globals)
  File "/opt/home/venv/lib/python2.7/linecache.py", line 14, in getline
lines = getlines(filename, module_globals)
 File "/opt/home/venv/lib/python2.7/linecache.py", line 40, in getlines
return updatecache(filename, module_globals)
 File "/opt/home/venv/lib/python2.7/linecache.py", line 127, in updatecache
with open(fullname, 'rU') as fp:
AttributeError: __exit__

这是我的测试代码:

m = mox.Mox()
m.StubOutWithMock(__builtin__, 'open')
mock_file = m.CreateMock(__builtin__.file)

open(mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(mock_file)
mock_file.write(mox.IgnoreArg()).MultipleTimes()
mock_file.close()

write_file_method()

【问题讨论】:

    标签: python unit-testing mocking mox


    【解决方案1】:

    __exit__ 是您尝试关闭文件时调用的方法。您的模拟文件不处理mock_file.close(),只是处理open()。您还需要模拟 close 方法。


    编辑:

    第二个,你为什么要模拟open? AFAIK你不应该这样做。被测方法应该采用开放流(例如,而不是文件名)。在生产代码中,客户端负责打开文件(例如pickle.dump)。在你的测试中,你传入一个StringIO,或者一个支持写作的模拟对象。


    编辑 2: 我会把你的方法一分为二,分别测试每一位。

    • 创建文件:在调用此方法之前检查该文件是否不存在,之后是否存在。有人可能会争辩说这种单行方法不值得测试。
    • 写入文件:见上文。创建一个StringIO 并写入其中,这样您的测试就可以验证是否写入了正确的内容。

    【讨论】:

    • 所以我添加一行说 m.StubOutWithMock(builtin, 'close')?我试过了,但我得到了同样的错误,除非我把它放在错误的地方(就在 m.StubOut 'open' 之后)
    • 我要测试的方法创建一个文件并写入它,所以我不传入文件对象或任何东西。我不知道还有什么方法可以测试它。
    • 我不认为这是open / close 接口,至少现在还不是。看起来问题在于他没有模拟上下文管理器界面,即__enter____exit__。仅供参考,关闭文件时不会调用__exit__,反之亦然。退出上下文管理器(with 块)时调用__exit__,然后它又调用close。看起来测试代码中的实际错误也被nose 吞噬了,因为nose 正在尝试打开一个文件以使用上下文管理器语法写入错误,但修补后的open 不支持它.
    • 去掉__enter____exit__,就是self.__mox.StubOutWithMock(__builtin__, '__enter__')之类的?
    • 这些是从open 返回的对象上的方法,而不是直接从__builtin__ 返回的东西。不过老实说,我认为您应该尝试找到另一种方法。您将以这种方式破坏您的测试记录。也许尝试编写一个包装器或其他东西来修补您的特定目标函数周围的局部变量/全局变量,这样您就不会影响依赖于被测代码之外的 open 的其他库。
    猜你喜欢
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-27
    • 2021-10-10
    • 2011-04-26
    • 1970-01-01
    相关资源
    最近更新 更多