Reputation: 33
This question has been asked here Pytest: How to test a function with input call?
But the answer by mareoraft (below) does not work for a function call it only works inside the current test function scope.
original answer:
def test_something_that_involves_user_input(monkeypatch):
# monkeypatch the "input" function, so that it returns "Mark".
# This simulates the user entering "Mark" in the terminal:
monkeypatch.setattr('builtins.input', lambda x: "Mark")
# go about using input() like you normally would:
i = input("What is your name?")
assert i == "Mark"
Here is test code where I moved the input to another function (this fails)
def separate_input_function():
a = input()
return a
def test_separate_function_monkeypatch_input(monkeypatch):
ans = '3'
with monkeypatch.context() as m:
m.setattr('builtins.input', lambda prompt: ans)
result = separate_input_function()
assert result == ans
This raises
TypeError: <lambda>() missing 1 required positional argument: 'prompt'
Any ideas on how to get this to work?
Thanks
Upvotes: 2
Views: 2013
Reputation: 7419
An alternative to patching is a technique called "dependency injection":
def separate_input_function(_input=input):
a = _input()
return a
def test_separate_function_monkeypatch_input(monkeypatch):
_input = lambda: 42
result = separate_input_function(_input=_input)
assert result == 42
Maybe this helps.
Upvotes: 0
Reputation: 365747
Your problem has nothing to do with moving the input
to a separate function, or even with monkeypatching; it has to do with passing the wrong number of arguments—just as the error message says.
In the example you refer to, the monkeypatching function is defined to take one parameter, and the input
call passes one argument.
If your own attempt, the monkeypatching function is defined to take one parameter, but the input
call passes no arguments.
You can just define it to take an optional parameter, just like the real input:
m.setattr('builtins.input', lambda prompt="": ans)
Upvotes: 3