检查多个模拟的调用顺序

Checking call order across multiple mocks(检查多个模拟的调用顺序)
本文介绍了检查多个模拟的调用顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我正在尝试测试三个函数的调用顺序.

I have three functions that I'm trying to test the call order of.

假设在模块 module.py 我有以下内容

Let's say that in module module.py I have the following

# module.py    

def a(*args):
    # do the first thing

def b(*args):
    # do a second thing

def c(*args):
    # do a third thing


def main_routine():
    a_args = ('a')
    b_args = ('b')
    c_args = ('c')

    a(*a_args)
    b(*b_args)
    c(*c_args)

我想检查 b 是否在 a 之后和 c 之前被调用.因此,为 a、b 和 c 中的每一个进行模拟很容易:

I want to check that b is called after a, and before c. So getting a mock for each of a, b and c is easy:

# tests.py

@mock.patch('module.a')
@mock.patch('module.b')
@mock.patch('module.c')
def test_main_routine(c_mock, b_mock, a_mock):
    # test all the things here

检查每个单独的模拟是否被调用也很容易.如何检查通话相对于彼此的顺序?

Checking that each of the individial mocks are called is easy, too. How do I check the order of the calls relative to one another?

call_args_list 不起作用,因为它是为每个模拟单独维护的.

call_args_list won't work as it's maintained separately for each mock.

我尝试使用副作用来记录每个调用:

I've tried using a side effect to log each of the calls:

calls = []
def register_call(*args):
    calls.append(mock.call(*args))
    return mock.DEFAULT

a_mock.side_effect = register_call
b_mock.side_effect = register_call
c_mock.side_effect = register_call

但这只会给我调用模拟的参数,而不是调用所针对的实际模拟.我可以添加更多逻辑:

But this only gives me the args that the mocks were called with, but not the actual mock that the call was made against. I can add a bit more logic:

# tests.py
from functools import partial

def register_call(*args, **kwargs):
    calls.append(kwargs.pop('caller', None), mock.call(*args, **kwargs))
    return mock.DEFAULT

a_mock.side_effect = partial(register_call, caller='a')
b_mock.side_effect = partial(register_call, caller='b')
c_mock.side_effect = partial(register_call, caller='c')

这似乎可以完成工作......但是有更好的方法吗?感觉 API 中应该已经有一些东西可以做到这一点,而我却错过了.

And that seems to get the job done... Is there a better way though? It feels like there should already be something in the API that can do this that I'm missing.

推荐答案

定义一个 Mock 管理器并通过 attach_mock().然后检查 mock_calls:

Define a Mock manager and attach mocks to it via attach_mock(). Then check for the mock_calls:

@patch('module.a')
@patch('module.b')
@patch('module.c')
def test_main_routine(c, b, a):
    manager = Mock()
    manager.attach_mock(a, 'a')
    manager.attach_mock(b, 'b')
    manager.attach_mock(c, 'c')

    module.main_routine()

    expected_calls = [call.a('a'), call.b('b'), call.c('c')]
    assert manager.mock_calls == expected_calls

只是为了测试它是否有效,更改 main_routine() 函数中的函数调用顺序,添加查看它是否抛出 AssertionError.

Just to test that it works, change the order of function calls in the main_routine() function add see that it throws AssertionError.

在 跟踪调用顺序和不那么冗长的调用断言

希望对您有所帮助.

这篇关于检查多个模拟的调用顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

patching a class yields quot;AttributeError: Mock object has no attributequot; when accessing instance attributes(修补类会产生“AttributeError:Mock object has no attribute;访问实例属性时)
How to mock lt;ModelClassgt;.query.filter_by() in Flask-SqlAlchemy(如何在 Flask-SqlAlchemy 中模拟 lt;ModelClassgt;.query.filter_by())
FTPLIB error socket.gaierror: [Errno 8] nodename nor servname provided, or not known(FTPLIB 错误 socket.gaierror: [Errno 8] nodename nor servname provided, or not known)
Weird numpy.sum behavior when adding zeros(添加零时奇怪的 numpy.sum 行为)
Why does the #39;int#39; object is not callable error occur when using the sum() function?(为什么在使用 sum() 函数时会出现 int object is not callable 错误?)
How to sum in pandas by unique index in several columns?(如何通过几列中的唯一索引对 pandas 求和?)