【问题标题】:Why does mocking 'open' and returning a FileNotFoundError raise AttributeError: __exit__?为什么模拟“打开”并返回 FileNotFoundError 会引发 AttributeError:__exit__?
【发布时间】:2016-08-12 13:05:34
【问题描述】:

通过使用FileNotFoundError 模拟open 进行测试,引发AttributeError: __exit__。为什么会发生这种情况,我可以做些什么来解决它?

以下代码打开一个简单的文本文件。如果文件丢失,它会生成一个默认值。它已通过定期运行进行检查,似乎运行良好。

so_main.py

import os

import so_config


def load_savelocation():
    path = os.path.join(so_config.ROOT, so_config.SAVELOCATION_FN)
    savelocation_path = os.path.normpath(path)
    try:
        with open(savelocation_path) as f:
            so_config.SAVELOCATION_PATH = f.readline()
    except FileNotFoundError:
        so_config.SAVELOCATION_PATH = so_config.ROOT

so_config.py

import os

ROOT, _ = os.path.split(__file__)
SAVELOCATION_PATH = None
SAVELOCATION_FN = 'savelocation.ini'

单元测试是另一回事。我在so.main 中模拟了open 命令。 test_so_main.py 有两个测试:一个用于正常打开存在的文件,另一个用于测试FileNotFoundError 处理。

常规文件打开的第一次测试test_read_path_from_disk_file_into_config_py 工作正常。

第二次测试失败,因为FileNotFoundError 引发了AttributeError: __exit__。 我可以将self.mock_open.return_value 设置为FileNotFoundError,或者我可以将其设置为'garbage'。没什么区别。

test_so_main.py

import unittest
import unittest.mock as mock

import so_config
import so_main


class TestReadSaveLocation(unittest.TestCase):
    def setUp(self):
        self.savelocation_path = so_config.SAVELOCATION_PATH
        self.root = so_config.ROOT
        so_config.ROOT = 'program root'
        p = mock.patch('so_main.open')
        self.mock_open = p.start()
        self.addCleanup(p.stop)

    def tearDown(self):
        so_config.SAVELOCATION_PATH = self.savelocation_path
        so_config.ROOT = self.root

    def test_read_path_from_disk_file_into_config_py(self):
        self.mock_open().__enter__().readline.return_value = 'data files location'
        so_main.load_savelocation()
        self.assertEqual('data files location', so_config.SAVELOCATION_PATH)

    def test_missing_file_defaults_savelocation_to_program_root(self):
        self.mock_open.return_value = FileNotFoundError
        so_main.load_savelocation()
        self.assertEqual('program root', so_config.SAVELOCATION_PATH)

我在 Windows 7 机器上通过 PyCharm 2016.2.1 运行 Python 3.5.2。

【问题讨论】:

    标签: python-3.x mocking python-unittest try-except


    【解决方案1】:

    您模拟函数以 return 一个异常,而不是 raise 它。

    尝试使用side_effect (docs):

    self.mock_open.side_effect = FileNotFoundError
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-03
      • 1970-01-01
      • 1970-01-01
      • 2013-07-13
      • 1970-01-01
      • 2010-12-19
      相关资源
      最近更新 更多