如何模拟单元测试的缓冲文件句柄



我希望它在没有缓冲的情况下正常工作:

$ tail -f logfile | python parser.py

以前我用过:

for line in sys.stdin:
    parse(line)

但现在我已经实现了https://stackoverflow.com/a/18235323/604515:

while True:
    line = sys.stdin.readline()
    if not line: break # EOF
    parse(line)

问题:我想不出一种方法可以在不睡觉的情况下对我的更改进行单元测试()。如何模拟缓冲文件句柄?我可以很容易地模拟stdin,但它将永远不会缓冲区,所以这不会证明什么。

编辑:我看过StringIO,但它似乎不像普通的文件句柄那样具有缓冲行为。

首先考虑通过传递流来参数化函数。您可以使用默认值来获取sys.stdout。你的方法变成了这样:

def my_reader(feed=sys.stdin):
    while True:
        line = feed.readline()
        if not line:
            break
        parse(line)

现在您可以通过mock框架和patchparse方法来模拟您的提要。不幸的是,您无法直接修补sys.stdin.readline()方法,因为它是只读属性。

现在测试中的步骤是:在setUp()中创建stdin的mock,并在测试中配置它并进行测试。举个例子。

#If you trust parse and you have no other way to test parse instead check its calls you need to patch it
@patch(__name__ + ".parse")
class MyTestCase(unittest.TestCase):
    def setUp(self):
        #Our 'feed'
        self.mock_feed = MagicMock()
        #readline mock
        self.mock_readline = self.mock_feed.readline
    def test_my_reader_empty(self, mock_parse):
        #setting up an empty stream
        self.mock_readline.return_value = ""
        my_reader(self.mock_feed)
        #Our test is that parse was never called
        self.assertFalse(mock_parse.called)
    def test_my_reader_some_lines(self, mock_parse):
        #setting up lines sequence and EOF
        self.mock_readline.side_effect = ["hi,n", "I'm your standard inputn", "cheers", ""]
        my_reader(self.mock_feed)
        #Call parse with every lines
        mock_parse.assert_has_calls([call("hi,n"), call("I'm your standard inputn"), call("cheers")])

只需注意:我修补了类,而不是修补了此处所述的所有方法。

最新更新