使用pytest模拟程序忽略assert_has_calls中的链接调用

时间:2018-09-17 18:23:19

标签: python python-3.x mocking pytest

在使用pytest-mock中的mocker时,如何使用has_calls来检查对特定方法的调用,而不检查对该方法的返回值的所有调用? >

例如:

import subprocess
from unittest import mock

def test_foo(mocker):
    m = mocker.patch('test_main.subprocess')
    r1 = subprocess.run(['foo'])
    r1.check_returncode()
    r2 = subprocess.run(['bar'])
    r2.check_returncode()

    m.run.assert_has_calls([
        mock.call(['foo']),
        mock.call(['bar']),
    ])

失败:

E       AssertionError: Calls not found.
E       Expected: [call(['foo']), call(['bar'])]
E       Actual: [call(['foo']),
E        call().check_returncode(),
E        call(['bar']),
E        call().check_returncode()]

为什么还包含对返回值的调用?我只想检查自己是否打过subprocess.run(['foo'])的电话,紧随其后是打到subprocess.run(['bar'])的电话。我不在乎对返回的任何内容的调用,但我要做在乎对run本身的调用顺序。

2 个答案:

答案 0 :(得分:2)

any_order=True添加到您的assert_has_calls呼叫中,如下所示:

m.run.assert_has_calls([
    mock.call(['foo']),
    mock.call(['bar']),
], any_order=True)

原因是,看起来assert_has_calls在基于文档(https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.mock_calls)的模拟中使用了mock_calls属性:

  

记录对模拟对象,其方法,魔术方法和返回值模拟的所有调用。

尽管有了assert_has_calls,这并不是一个完全匹配的问题,只是排序失败了。

编辑:由于顺序很重要,请使用call_args_list。像这样:

def test_foo(mocker):
    m = mocker.patch('subprocess_test.subprocess')
    r1 = subprocess.run(['foo'])
    r1.check_returncode()
    r2 = subprocess.run(['bar'])
    r2.check_returncode()

    assert [mock.call(['foo']), mock.call(['bar'])] == m.run.call_args_list

答案 1 :(得分:0)

使用assert_any_call

m.run.assert_any_call(['foo'])
m.run.assert_any_call(['bar'])