模拟打开(文件)中的行:

use*_*088 4 python unit-testing mocking

我想对我的应用程序的一个组件进行单元测试.代码看起来有点像下面.

def read_content_generator(myfile):
    for line in open(myfile):
        # do some string manipulation.
        yield result
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是我无法open()在for循环中模拟功能.

我的目标是unittest这样的:(我知道这段代码不对,但它只是我想要做的一个例子):

def test_openiteration(self):
    with mock.patch('open') as my_openmock:
        my_openmock.return_value = ['1','2','3']
        response = myfunction()
        self.assertEquals([1,2,3], response)
Run Code Online (Sandbox Code Playgroud)

and*_*and 7

您可以模拟open()返回StringIO对象.

mymodule.py:

def read_content_generator(myfile):
    with open(myfile) as f:
        for line in f:
            yield '<{}>'.format(line)
Run Code Online (Sandbox Code Playgroud)

请注意,我在那里使用了声明.

test_mymodule.py:

import io
import unittest
import unittest.mock as mock

import mymodule


class Tests(unittest.TestCase):
    def test_gen(self):
        fake_file = io.StringIO('foo\nbar\n')
        with mock.patch('mymodule.open', return_value=fake_file, create=True):
            result = list(mymodule.read_content_generator('filename'))
        self.assertEqual(result, ['<foo\n>' , '<bar\n>'])
Run Code Online (Sandbox Code Playgroud)

适用于python3.4.

起初我尝试使用,mock.mock_open(read_data='1\n2\n3\n')但迭代支持似乎被打破.


Vee*_*rac 1

有两个简单的选择:

  • 更改read_content_generator为采用文件而不是文件名,并使用io.StringIO.

  • 制作一个临时文件。有一些很好的模块可以做到这一点。