为什么嘲笑“打开"并返回FileNotFoundError会引发AttributeError:__exit__? [英] Why does mocking 'open' and returning a FileNotFoundError raise AttributeError: __exit__?

查看:89
本文介绍了为什么嘲笑“打开"并返回FileNotFoundError会引发AttributeError:__exit__?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过使用FileNotFoundError模拟open进行测试会引发AttributeError: __exit__.为什么会发生这种情况,我该怎么解决?

Testing by mocking open with a FileNotFoundError raises AttributeError: __exit__. Why is this happening and what can I do to fix it?

以下代码打开一个简单的文本文件.如果文件丢失,它将生成一个默认值.已通过常规运行进行了检查,它似乎运行正常.

The following code opens a simple text file. If the file is missing it generates a default value. It has been checked by regular running and it appears to be working perfectly.

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处理.

The unittests are a different story. I've mocked the open command in so.main. test_so_main.py has two tests: One for normal opening of a file which is present and a second to test the FileNotFoundError handling.

常规打开文件test_read_path_from_disk_file_into_config_py的第一个测试工作正常.

The first test of regular file opening test_read_path_from_disk_file_into_config_py works fine.

第二次测试失败,因为FileNotFoundError提高了AttributeError: __exit__. 我可以将self.mock_open.return_value设置为FileNotFoundError或将其设置为'garbage'.没关系.

The second test fails because the FileNotFoundError raises AttributeError: __exit__. I can set self.mock_open.return_value to FileNotFoundError or I can set it to 'garbage'. It doesn't make any difference.

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.

I'm running Python 3.5.2 via PyCharm 2016.2.1 on a Windows 7 machine.

推荐答案

您可以模拟该函数以返回异常,而不是 raise .

You mock the function to return an exception instead of raise it.

尝试使用side_effect(文档):

self.mock_open.side_effect = FileNotFoundError

这篇关于为什么嘲笑“打开"并返回FileNotFoundError会引发AttributeError:__exit__?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆