How do I mock the Python method OptionParser.error(), which does a sys.exit()?
我正在尝试对如下代码进行单元测试:
1 2 3 4 5 6 7 8 9 10 11 | def main(): parser = optparse.OptionParser(description='This tool is cool', prog='cool-tool') parser.add_option('--foo', action='store', help='The foo option is self-explanatory') options, arguments = parser.parse_args() if not options.foo: parser.error('--foo option is required') print"Your foo is %s." % options.foo return 0 if __name__ == '__main__': sys.exit(main()) |
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @patch('optparse.OptionParser') def test_main_with_missing_p4clientsdir_option(self, mock_optionparser): # # setup # optionparser_mock = Mock() mock_optionparser.return_value = optionparser_mock options_stub = Mock() options_stub.foo = None optionparser_mock.parse_args.return_value = (options_stub, sentinel.arguments) def parser_error_mock(message): self.assertEquals(message, '--foo option is required') sys.exit(2) optionparser_mock.error = parser_error_mock # # exercise & verify # self.assertEquals(sut.main(), 2) |
号
我用迈克尔·福德的模型和鼻子来做测试。
当我运行测试时,我得到:
1 2 3 4 5 6 7 8 | File"/Users/dspitzer/Programming/Python/test-optparse-error/tests/sut_tests.py", line 27, in parser_error_mock sys.exit(2) SystemExit: 2 ---------------------------------------------------------------------- Ran 1 test in 0.012s FAILED (errors=1) |
问题是optionParser.error执行sys.exit(2),因此main()自然依赖于此。但是nose或unittest检测到(预期的)系统出口(2),并且测试失败。
我可以通过在main()中的parser.error()调用下添加"return 2"并从parser_error_mock()中删除sys.exit()调用来通过测试,但我发现修改测试中的代码以允许测试通过令人不快。有更好的解决方案吗?
更新:虽然正确的调用是"self.assertraises(systemexit,sut.main)",但df的答案是有效的。
这意味着测试通过解析器中sys.exit()中的任何数字。有没有办法测试退出代码?
顺便说一句,如果我加上:
1 | self.assertEquals(optionparser_mock.method_calls, [('add_option', ('--foo',), {'action': 'store', 'help': 'The foo option is self-explanatory'}), ('parse_args', (), {})]) |
。
最后。
更新2:我可以通过将"self.assertraises(systemexit,sut.main)"替换为以下内容来测试退出代码:
1 2 3 4 5 6 7 8 9 | try: sut.main() except SystemExit, e: self.assertEquals(type(e), type(SystemExit())) self.assertEquals(e.code, 2) except Exception, e: self.fail('unexpected exception: %s' % e) else: self.fail('SystemExit exception expected') |
这能代替
1 | self.assertRaises(SystemExit, sut.main, 2) |
这应该捕获
正如我对问题的更新所指出的,我必须修改df的答案:
1 | self.assertRaises(SystemExit, sut.main) |
号
…我想出了一些更长的代码片段来测试退出代码。
[注:我接受了我自己的答案,但如果DF更新了他的答案,我将删除此答案并接受其答案。]
在测试函数中添加
1 2 3 4 5 6 7 8 | from nose.tools import raises @raises(SystemExit) @patch('optparse.OptionParser') def test_main_with_missing_p4clientsdir_option(self, mock_optionparser): # Setup ... sut.main() |
这个问题可能包含一些新信息:
Java:如何测试调用Stule.ExITE()的方法?