如果使用不同的属性多次调用它,如何模拟方法?

时间:2015-02-18 13:04:22

标签: python unit-testing mocking fabric

我正在为基于PythonFabric的代码编写单元测试。我有以下方法,它反过来使用不同的参数多次调用Fabric API的sudo方法。我想知道如何在mock sudo对象上调用assert。有人可以帮我吗?

**main_file.py**

from fabric.api import sudo

def do_something(path_to_file_to_be_copied, destination_path):
    # remove file if already exists
    sudo('rm ' + path_to_file_to_be_copied, warn_only=True)
    sudo('cp ' + path_to_file_to_be_copied + ' ' + destination_path)

我已经编写了如下测试文件:

**test_main_file.py**

import main_file

class MainFileTest(unittest.TestCase):

    @mock.patch('main_file.sudo')
    def test_do_something(self, mock_sudo):
        file_path = '/dummy/file/path.txt'
        dest_dir = '/path/to/dest/dir'
        main_file.do_something(file_path, dest_dir)
        mock_sudo.assert_called_with('rm ' + file_path)

上面的测试失败,因为模拟对象只记得最后一次调用。也就是说,如果我写mock_sudo.assert_called_with(cp + file_path + ' ' + dest_dir),那么测试失败。

任何人都可以告诉我如何断言对sudo的调用?

3 个答案:

答案 0 :(得分:1)

尝试assert_any_call断言是否有任何电话,而不仅仅是最近的电话。

或者,您可以使用call_args_list来获取调用mock的args列表。

答案 1 :(得分:0)

assert_has_calls将为您完成这项工作。

  

assert_has_calls:断言已使用指定的调用调用了mock。检查mock_calls列表是否有呼叫   如果any_order为true,那么调用可以是任何顺序,但它们必须全部出现在mock_calls中。

import main_file
class MainFileTest(unittest.TestCase):

    @mock.patch('main_file.sudo')
    def test_do_something(self, mock_sudo):
        file_path = '/dummy/file/path.txt'
        dest_dir = '/path/to/dest/dir'
        main_file.do_something(file_path, dest_dir)
        mock_sudo.assert_has_calls(['rm ' + file_path,
                                    'cp' + file_path + ' ' + dest_dir],
                                     any_order=True)

答案 2 :(得分:0)

我写了helper library为我自动生成断言。

添加这些行以在main_file.do_something(file_path, dest_dir)之后紧随您的情况打印正确的断言:

import mock_autogen.generator
print(mock_autogen.generator.generate_asserts(mock_sudo))

您将获得以下输出:

from mock import call

assert 2 == mock_sudo.call_count
mock_sudo.assert_has_calls(
    calls=[call('rm /dummy/file/path.txt', warn_only=True),
           call('cp /dummy/file/path.txt /path/to/dest/dir'), ])

不再需要猜测,请使用mock-generator:)