我正在尝试为我的带有返回值和sys.stdout
的单元测试测试函数创建一个Python Mixin。我希望Mixin有一种方法可以用作吞咽sys.stdout
的装饰器,但是到目前为止我还没有成功。
我的自定义装饰器应该:
sys.stdout
unittest.mock.patch
函数作为装饰器以实现我对装饰器的尝试:
import io
import sys
import unittest.mock
class StdoutUnittestMixin(unittest.TestCase):
@unittest.mock.patch('sys.stdout', new_callable=io.StringIO)
def monkey_patch_stdout(self, original_function, mock_stdout):
def wrapper_function(*args, **kwargs):
captured_output = io.StringIO() # Create StringIO object
sys.stdout = captured_output # and redirect stdout.
return_value = original_function(*args, **kwargs) # Call unchanged function.
sys.stdout = sys.__stdout__ # Reset redirect.
return return_value
return wrapper_function
已测试功能的示例:
def foo(some_str):
print(some_str)
return some_str.isnumeric()
在单元测试中需要使用修饰器:
class Testing(unittest.TestCase):
@monkey_patch_stdout # The decorator wants inputs - I don't want that
def test_function_outputs_true(self):
self.assertTrue(foo("123"))
按预期,我得到:
TypeError: assert_True() missing 1 required positional argument: 'mock_stdout'
因此,我知道mock_stdout
必须在那儿,因为unittest.mock.patch
装饰者需要这样做。
答案 0 :(得分:0)
我发现有两个问题:
1)正如@kdojeteri通知我的,谢谢,使用IN
装饰器复制了猴子补丁逻辑
2)unittest.patch.mock
行弄乱了事情。当我将对sys.stdout = sys.__stdout__
的引用保存到一个新变量中,然后使用它来重置sys.stdout
时,它起作用了。
尽管不满足我的要求之一,但最终的工作代码如下。
mixin方法:
sys.stdout
已测试的功能:
import io
import sys
import unittest.mock
class StdoutUnittestMixin(unittest.TestCase):
@staticmethod
def monkey_patch_stdout(original_function):
"""
:param original_function: Decorated function which is expected to have stdout
:return: Wrapped function which uses monkey patching for the sys.stdout object
"""
def wrapper_function(*args, **kwargs):
captured_output = io.StringIO() # Create StringIO object
my_stdout = sys.stdout # Saving reference for sys.stdout
sys.stdout = captured_output # and redirect stdout.
return_value = original_function(*args, **kwargs) # Call unchanged function.
sys.stdout = my_stdout # Reset redirect.
return return_value
return wrapper_function
测试方法:
def foo(some_str):
print(some_str)
return some_str.isnumeric()