如何在 BDD 步骤文件中进行模拟

Cra*_*aig 6 python bdd mocking python-behave

我想模拟 os.path.exists 方法的行为,以便在 os.path.exists 报告文件/文件夹不存在时验证我的脚本是否行为正确。

@when("Service starts with input file that does not exist")
def step_impl(context):
    """
    :type context: behave.runner.Context
    """
    json_file_path = "fake_file_path"
    mock_os_path = mock.Mock()
    mock_os_path.exists.return_value = False

    context.returncode = dicom_send_service.launch(json_file_path)

    mock_os_path.exists.assert_called_once_with(json_file_abspath)
Run Code Online (Sandbox Code Playgroud)

如何将模拟注入到我的脚本中?我尝试使用

@mock.patch("mymodule.os.path")
@when("Service starts with input file that does not exist")
def step_impl(context, mock_os_path):
Run Code Online (Sandbox Code Playgroud)

但是,当我运行该方法时,python 返回:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/behave/model.py", line 1456, in run
    match.run(runner.context)
  File "/usr/local/lib/python2.7/dist-packages/behave/model.py", line 1903, in run
    self.func(context, *args, **kwargs)
TypeError: step_impl() takes exactly 2 arguments (1 given)
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,step_impl 方法根据声明需要 2 个参数,但 BDD 仅使用 1 个(上下文值)来调用它,并且没有选取模拟注释。

这是我正在测试的代码:

import os

def validate(json_file_path):
    """Method which validates the JSON file, an error message is returned if the file fails verification.

        json_file_path -- the path to the file with the message configuration details"""
    if not os.path.exists(json_file_path):
        return "Could not find file at path {0}".format(json_file_path)
    ...
    return ""

def launch(json_file_path):
    error_message = valid(json_file_path)
    if error_message:
        print(error_message)
        return 1
Run Code Online (Sandbox Code Playgroud)

Cra*_*aig 6

因此,要回答我自己的问题,您必须使用以下with mock.patch语法:

with mock.patch('name of thing to mock') as name_of_mock:
Run Code Online (Sandbox Code Playgroud)

所以我上面的例子将变成:

@when("Service starts with input file that does not exist")
def step_impl(context):
    """
    :type context: behave.runner.Context
    """
    json_file_path = "fake_file_path"

    # This is where the magic happens
    with mock.patch ('os.path') as mock_os_path:

        mock_os_path.exists.return_value = False

        context.returncode = dicom_send_service.launch(json_file_path)

        mock_os_path.exists.assert_called_once_with(json_file_abspath)
Run Code Online (Sandbox Code Playgroud)

我已经测试过了,它的效果就像一个魅力。比使用 Java 中的 Mockito 或 Powermock 等其他模拟框架容易得多。