我正在尝试使用pytest fixture来模拟调用open(),然后在测试拆卸时重置它,但由于某种原因,mock不会应用于测试函数中.
这是我的样本:
# tests.py
@pytest.fixture(scope='module')
def mock_open(request):
mock = flexmock(sys.modules['__builtin__'])
mock.should_call('open')
m = (mock.should_receive('open')
.with_args('/tmp/somefile')
.and_return(read=lambda: 'file contents'))
request.addfinalizer(lambda: m.reset())
def test_something(mock_open):
ret = function_to_test()
ret[1]() # This actually uses the original open()
Run Code Online (Sandbox Code Playgroud)
而且,如果它很重要,这就是function_to_test()看起来像:
# some_module.py
def function_to_test():
def inner_func():
open('/tmp/somefile').read() # <-- I want this call mocked
# More code ...
return (True, inner_func)
Run Code Online (Sandbox Code Playgroud)
如果我使用xUnit-style setup_module()/ teardown_module()functions 也会发生这种情况.但是如果我把模拟代码放在测试函数本身(我显然不想这样做),那么它工作正常.
我错过了什么?谢谢!
我正在尝试模拟我将要使用的 python 脚本的用户输入py.test。下面是一些代表我想要完成的基本代码:
def ask():
while True:
age = input("Enter your age: ")
if int(age) < 13:
print("You are too young")
else:
name = input("Enter your name: ")
break
print("Welcome!")
Run Code Online (Sandbox Code Playgroud)
我想模仿用户输入并读取输出。一个例子可能是这样的:
@mock.patch('builtins.input', side_effect=['11'])
def test_invalid_age():
ask()
assert stdout == "You are too young"
Run Code Online (Sandbox Code Playgroud)
我也听说这flexmock可能是内置模拟unittest系统的更好替代方案,但此时我会采取任何解决方案。
更新:
我玩了更多,并进行了一个测试:
@mock.patch('builtins.input', side_effect=['11'])
def test_bad_params(self, input):
ask()
output = sys.stdout.getline().strip()
assert output == "You are too young"
Run Code Online (Sandbox Code Playgroud)
当我运行 py.test 我得到这个结果:
E StopIteration /usr/lib/python3.3/unittest/mock.py:904:
StopIteration
Run Code Online (Sandbox Code Playgroud)
它确实捕获了适当的标准输出调用“你太年轻了”。