如何模拟打开文件并在路径不存在时引发?

问题描述 投票:0回答:1

我在测试读取文件第一行的函数时遇到问题,并在文件路径不存在时引发

Exception

当前代码:

from unittest.mock import patch, mock_open
from pytest import raises
from os.path import exists

def read_from_file(file_path):
    if not exists(file_path):
        raise Exception("File does not exists!")
    with open(file_path, "r") as f:
        return f.read().splitlines()[0]

@patch("builtins.open", new_callable=mock_open, read_data="Correct string\nWrong string\nWrong string")
@patch("os.path.exists", return_value=True)
def test_read_file_and_returns_the_correct_string_with_multiple_lines(mock_os, mock_file):
    result = read_from_file("xyz")
    mock_file.assert_called_once_with("xyz", "r")
    assert result == "Correct string"

@patch("builtins.open", new_callable=mock_open, read_data="Correct string")
@patch("os.path.exists", return_value=False)
def test_throws_exception_when_file_doesnt_exist(mock_os, mock_file):
    with raises(Exception):
        read_from_file("xyz")

装饰器

@patch("os.path.exists", return_value=True)
@patch("os.path.exists", return_value=False)
在这两个测试中似乎都没有效果。

如何模拟文件的存在?

python pytest python-unittest python-unittest.mock pytest-mock
1个回答
0
投票

您面临的问题与

@patch
装饰器的顺序有关。装饰器是从最内层到最外层应用的。因此,在您的测试中,
mock_file
参数对应于
builtins.open
,而
mock_os
参数对应于
os.path.exists

当您模拟多个对象时,模拟的对象将按照补丁装饰器出现的顺序传递给测试函数。在您的情况下,您应该切换函数签名中模拟参数的顺序以匹配装饰器。

from unittest.mock import patch, mock_open
from pytest import raises
from os.path import exists

def read_from_file(file_path):
    if not exists(file_path):
        raise Exception("File does not exists!")
    with open(file_path, "r") as f:
        return f.read().splitlines()[0]

@patch("os.path.exists", return_value=True)
@patch("builtins.open", new_callable=mock_open, read_data="Correct string\nWrong string\nWrong string")
def test_read_file_and_returns_the_correct_string_with_multiple_lines(mock_file, mock_os):
    result = read_from_file("xyz")
    mock_file.assert_called_once_with("xyz", "r")
    assert result == "Correct string"

@patch("os.path.exists", return_value=False)
@patch("builtins.open", new_callable=mock_open, read_data="Correct string")
def test_throws_exception_when_file_doesnt_exist(mock_file, mock_os):
    with raises(Exception):
        read_from_file("xyz")
© www.soinside.com 2019 - 2024. All rights reserved.