pytest:如何模拟不存在的文件打开?

时间:2018-11-04 07:46:53

标签: unit-testing pytest

我是pytest的新手。 考虑以下代码

def myFunc():
    with open('/tmp/file.json', 'r') as f:
         json_data = json.load(f)
    return

如何为此功能编写测试用例? 请注意,运行UnitTest的服务器中将不存在“ /tmp/file.json”

3 个答案:

答案 0 :(得分:0)

您选择了一段不幸的代码来开始进行单元测试:myFunc之类的功能通常未经单元测试:相反,通常创建此类功能是为了将与环境的交互与“其余代码”,只是为了使“其余代码”更易于单元测试。然后,在测试“其余代码”时,可以用模拟代替myFunc,以便模拟不同的文件内容或丢失的文件。

对于myFunc之类的测试功能,集成测试(与单元测试完全不同)是一种更合适的测试方法。

答案 1 :(得分:0)

这种情况的一个选择是,稍微改变你的代码

file.py 的内容

TMP_FILE = '/tmp/file.json'
def my_func(file=TMP_FILE):
    with open(TMP_FILE, 'r') as f:
         json_data = json.load(f)
return

在你的 test_file.py 中

TMP_FILE = 'tmp_file.py'

@pytest.fixture
def tmp_file():
    with open(TMP_FILE, 'w') as file:
        file.write('sample content')
    yield TMP_FILE
    os.remove(TMP_FILE)

def test_my_func(tmp_file):
   my_func(tmp_file)

这是使用文件的方法,但要进行真正的测试,也许您应该考虑使用 json 模式进行某种断言: 文件.py

TMP_FILE = '/tmp/file.json'
def my_func(file=TMP_FILE):
    with open(TMP_FILE, 'r') as f:
         json_data = json.load(f)
    return validate(instance=json_data, schema=schema)

test_file.py

def test_my_func():
   assert my_func(TMP_FILE)

或多或少

答案 2 :(得分:0)

可能有点矫枉过正,但包 pyfakefs 负责模拟虚拟文件。在文档中,有这个 example:

from pyfakefs.fake_filesystem_unittest import Patcher

with Patcher() as patcher:
    # access the fake_filesystem object via patcher.fs
    patcher.fs.create_file('/foo/bar', contents='test')

    # the following code works on the fake filesystem
    with open('/foo/bar') as f:
        contents = f.read()

这允许您模拟具有自定义内容的文件。

在你的情况下,这样的事情可以工作:

from pyfakefs.fake_filesystem_unittest import TestCase

class ExampleTestCase(TestCase):
    def setUp(self):
        self.setUpPyfakefs()

    def test_create_file(self):
        file_path = '/tmp/file.json'
        test_content = '{"foo": "bar"}'
        self.assertFalse(os.path.exists(file_path))
        self.fs.create_file(file_path, contents=test_content)
        self.assertTrue(os.path.exists(file_path))
        myFunc() # Test behavior after this