当前位置: 首页 > 面试题库 >

检查多个模拟的呼叫顺序

通安宁
2023-03-14
问题内容

我要尝试测试其呼叫顺序的三个功能。

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

# 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中的每一个进行模拟都是容易的:

# 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

检查每个单独的模拟都被调用也很容易。如何检查呼叫相对于彼此的顺序?

call_args_list 将无法使用,因为每个模拟都单独维护。

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

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

但这仅给我提供了与模拟一起调用的args,而没有给实际调用的模拟。我可以添加更多逻辑

# 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中应该已经有某些东西可以做到这一点,而我所缺少的。


问题答案:

定义一个Mock管理器,并通过附加模拟attach_mock()。然后检查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()请在函数add中更改函数调用的顺序,以查看它是否抛出了AssertionError

请参阅跟踪呼叫顺序和较少冗长的呼叫断言中的更多示例

希望能有所帮助。



 类似资料:
  • 问题内容: 我想使用Mockito测试下面的(简化)代码。我不知道如何告诉Mockito第一次失败,然后第二次成功。 我可以通过以下方式设置成功测试: 以及失败测试: 但是,如何测试一次失败(或两次)然后成功,就可以了吗? 问题答案: 从文档: 有时,对于同一方法调用,我们需要对不同的返回值/异常进行存根。典型的用例可能是模拟迭代器。Mockito的原始版本没有此功能来促进简单的模拟。例如,可以使

  • 如果使用基于回调的异步测试,如果done()多次调用Mocha,则会抛出错误。这对于捕获意外的双重回调非常方便。 it('double done', function(done) { // Calling `done()` twice is an error setImmediate(done); setImmediate(done); }); 运行上面的测试将给出以下错误消息: $ ./nod

  • 问题内容: 我正在尝试模拟一些基于反射的方法。您可以在下面看到详细信息, 被测课程 测试 } 要么 但是,测试失败,并显示NullPointerException。我知道我在嘲笑概念上做错了什么,但是我不明白这是什么。您能否对此加以说明,并建议我如何测试此方法? 谢谢。 问题答案: 您需要一个Method对象和一个Class对象。根据您的评论,Mockito无法模拟方法,因此您需要一个真正的方法。

  • 问题内容: 那是测试的方法 我必须模拟三个CacheContext,Method和CacheEnable。有什么想法可以使测试用例更加简单吗? 问题答案: Mockito 可以处理链接的存根: AFAIK,链中的第一个方法返回一个模拟,该模拟被设置为在第二个链式方法调用中返回您的值。 Mockito的作者注意到,这 仅应用于遗留代码 。否则,更好的方法是将行为推送到CacheContext并提供完

  • 我是RXJava的新手。在一个场景中,我希望调用第一个登录webservice(),如果成功,则希望调用另一个webservice()以获取用户信息。

  • 当我运行app时,它在logcat中显示这个 java.lang.SecurityException:权限拒绝:从ProcessRecord{2dd511f 24656:com.marg.pharmanxt/u0a158}(PID=24656,UID=10158)中启动意图{act=android.Intent.action.call dat=tel:xxxxxxxxxcapt=2dd511f 2