我想在自定义管理命令中测试用户输入确认答案。该测试用于向用户显示消息并回答她输入的内容。
命令的代码是:
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('id', type=int)
def handle(self, *args, **options):
try:
experiment = Experiment.objects.get(pk=options['id'])
except Experiment.DoesNotExist:
raise CommandError(
'Experiment with id "%d" does not exist' % (options['id'])
)
answer = input('Are you sure? (Y/n)')
if answer == 'Y':
experiment.delete()
这accepted answer建议使用模仿,但它处于孤独的环境中。我想测试用户输入以及我可以添加到自定义命令的其他内容。
什么是有效的方法?
答案 0 :(得分:1)
在搜索了几个来源之后,我找不到一个类似于我的问题的解决方案。所以我混合了一些使用python mock
库来获得一个简洁的解决方案。
测试方法(在test_commands.py中):
from unittest.mock import patch
# other imports
@patch('experiments.management.commands.remove_experiment.get_input',
return_value='Y')
def test_remove_experiment_displays_prompt_and_user_confirm_removing(
self, mock_user_input
):
experiment = create_experiment()
out = StringIO()
call_command(
'remove_experiment', experiment.id, stdout=out
)
self.assertEqual(mock_user_input.called, True)
(text,), kwargs = mock_user_input.call_args
self.assertEqual(text,
'All versions of experiment "%s" will be destroyed and cannot be '
'recovered. Are you sure? (Yes/n) ' % experiment.title)
self.assertFalse(Experiment.objects.exists())
现在,在命令类中,我们在方法中包含python input()
(就像问题中提到的accepted answer中所做的那样)。
<强> my_app.management.commands.remove_experiment 强>:
def get_input(text):
return input(text)
class Command(BaseCommand):
def add_arguments(self, parser):
parser.add_argument('id', type=int)
def handle(self, *args, **options):
try:
experiment = Experiment.objects.get(pk=options['id'])
except Experiment.DoesNotExist:
raise CommandError(
'Experiment with id "%d" does not exist' % (options['id'])
)
answer = get_input('Are you sure? (Y/n)')
if answer == 'Y':
experiment.delete()
现在,测试将验证问题文本,在用户输入提示中是正确的,但不会在stdout
中显示。此外,return_value='Y'
上下文装饰器中的kwarg @patch
将模拟用户答案,并且测试通过。