Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 模拟打印,但允许在测试中使用_Python 3.x_Mocking_Unit Testing - Fatal编程技术网

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")