Python 3.x 模拟打印,但允许在测试中使用
可以通过以下方式模拟打印:Python 3.x 模拟打印,但允许在测试中使用,python-3.x,mocking,unit-testing,Python 3.x,Mocking,Unit Testing,可以通过以下方式模拟打印: import unittest import builtin class TestSomething(unittest.TestCase): @mock.patch('builtins.print') def test_method(self, print_): some_other_module.print_something() 然而,这意味着在python调试控制台(pydev调试器)和单元测试方法本身中不能使用print。这
import unittest
import builtin
class TestSomething(unittest.TestCase):
@mock.patch('builtins.print')
def test_method(self, print_):
some_other_module.print_something()
然而,这意味着在python调试控制台(pydev调试器)和单元测试方法本身中不能使用print
。这相当不方便
是否有一种方法可以只模拟some_other_模块
中的print
方法,而不模拟测试模块中的方法
避免这种情况的一种方法是,将测试模块中打印的使用与一些只调用
print
的其他函数交换,如果没有更好的解决方案,我可以这样做。是的,您可以。。。但是仅仅因为您使用的是Python 3。在Python3中,print是一个函数,您可以在不更改名称的情况下重写它。为了理解最终的解决方案,我将一步一步地描述它,以获得最终的灵活且非侵入性的解决方案
仪器模块
诀窍是在模块顶部添加测试行,如:
print = print
现在,您可以修补模块的打印。我编写了一个测试用例,其中mock\u print\u module.py
是:
print = print
def print_something():
print("print something")
测试模块(我使用autospec=True
只是为了避免类似mock\u print.asser\u的错误,用调用了\u):
我不想更改我的模块,只想在不丢失功能的情况下进行补丁打印
只需使用副作用补丁的属性,您就可以在内置.print“
上使用补丁
,而不会丢失打印功能:
@patch("builtins.print",autospec=True,side_effect=print)
def test_somethingelse(self,mock_print):
mock_print_module.print_something()
mock_print.assert_called_with("print something")
现在,您可以跟踪prints调用,而不会丢失日志记录和pydev调试器。这种方法的缺点是,您必须与大量噪音作斗争,以检查您感兴趣的打印调用。此外,您不能选择要修补的模块和不修补的模块
两种模式不能同时工作
不能同时使用这两种方式,因为如果在模块中使用print=print
,则在加载模块时将内置项保存在print
变量中。现在,当您修补内置。打印时,模块仍使用原始保存的模块
如果你有机会同时使用这两种方法,你必须将原稿包装起来,而不仅仅是记录下来。实现它的一种方法是使用以下方法,而不是使用print=print
:
import builtins
print = lambda *args,**kwargs:builtins.print(*args,**kwargs)
最终解决方案
我们真的需要修改原始模块以有机会修补其中的所有打印调用吗?不,我们可以在不改变模块的情况下进行测试。我们唯一需要的是在模块中注入一个本地print
函数来覆盖内置的功能:我们可以在测试模块中而不是在要测试的模块中执行。我的例子是:
from unittest import TestCase
from unittest.mock import patch
import mock_print_module
import builtins
mock_print_module.print = lambda *args,**kwargs:builtins.print(*args,**kwargs)
class MyTestCase(TestCase):
@patch("mock_print_module.print",autospec=True)
def test_something(self,mock_print):
mock_print_module.print_something()
mock_print.assert_called_with("print something")
@patch("builtins.print",autospec=True,side_effect=print)
def test_somethingelse(self,mock_print):
mock_print_module.print_something()
mock_print.assert_called_with("print something")
和mock_print_module.py
可以是干净的原始版本,只需:
def print_something():
print("print something")
@michele的“最终解决方案”有一个更干净的替代方案,在我的案例中也适用:
from unittest import TestCase
from unittest.mock import patch
import module_under_test
class MyTestCase(TestCase):
@patch('module_under_test.print', create=True)
def test_something(self, print_):
module_under_test.print_something()
print_.assert_called_with("print something")
你还对这个问题感兴趣吗?很好!简单,没有任何其他进口类别等。伟大的解决方案!非常感谢。
from unittest import TestCase
from unittest.mock import patch
import module_under_test
class MyTestCase(TestCase):
@patch('module_under_test.print', create=True)
def test_something(self, print_):
module_under_test.print_something()
print_.assert_called_with("print something")