简体   繁体   English

我如何使用 Python MonkeyPatch + Mock 断言调用了 function

[英]How can I use Python MonkeyPatch + Mock to assert that a function was called

I have a test library using MonkeyPatch for testing some functionality.我有一个使用 MonkeyPatch 测试某些功能的测试库。 I would like to add a test to this library to test that a request to my endpoint calls functionB().我想向该库添加一个测试,以测试对我的端点调用 functionB() 的请求。

I have used Mock() library to create the mock function, that I then pass using MonkeyPatch.setattr().我使用 Mock() 库创建模拟 function,然后使用 MonkeyPatch.setattr() 传递它。 However, the mock function is never getting called and the assertion always fails.但是,模拟 function 永远不会被调用,断言总是失败。 What am I doing wrong?我究竟做错了什么?

mock_function_B = Mock()
monkeypatch.setattr(file, 'function_B', mock_function_B)
params = json.dumps({'foo': "bar"})
res = client.post('/some_endpoint', headers=content_type_json, data=params)
assert res.status_code == 201
assert mock_function_B.call_count == 1

I expect call_count to be 1, as I know that some_endpoint calls function_B (and from the logs, I see that it has been called) However, the assertion fails because call_count is 0.我希望 call_count 为 1,因为我知道 some_endpoint 调用 function_B(并且从日志中,我看到它已被调用)但是,断言失败,因为 call_count 为 0。

It can be done in different ways, as an example you can mock function_B and count the calls in a local variable.它可以通过不同的方式完成,例如,您可以模拟 function_B 并计算局部变量中的调用次数。

calls = []
monkeypatch.setattr(file, 'function_B', lambda a*, **k: calls.append('Called!'))
params = json.dumps({'foo': "bar"})
res = client.post('/some_endpoint', headers=content_type_json, data=params)
assert res.status_code == 201
assert len(calls) == 1

I you use the package pytest-mock , you can check for the number of calls of a mocked function and for the arguments the function was called with .如果你使用 package pytest-mock ,你可以检查模拟 function的调用次数,对于arguments 调用 function

import sys

def my_fct(*args, **kwargs):
    return 7

def test_call_fct_count2(monkeypatch, mocker):

    # prepare: mock my_fct to return 99
    monkeypatch.setattr(__name__ + '.my_fct', lambda *args, **kwargs: 99)
    spy = mocker.spy(sys.modules[__name__], 'my_fct')  # how to use: spy(module/object, function or method as str)

    # use mocked function (and assert it is mocked)
    assert my_fct() == 99
    assert my_fct('arg0', 1, 'arg2') == 99
    assert my_fct(my_var=3) == 99

    # now we check how and how often my_fct-mock was called
    assert spy.call_count == 3
    my_fct.assert_any_call()
    my_fct.assert_any_call('arg0', 1, 'arg2')
    my_fct.assert_called_with(my_var=3)  # last call

__name__ is needed here as a placeholder for the current modules name.此处需要__name__作为当前模块名称的占位符。 This is just the filename of the python script.这只是 python 脚本的文件名。 When you refer to a function from another module , you need to specify that module as the first arg of setattr and spy .当您从另一个模块引用 function 时,您需要将该模块指定为setattrspy第一个参数

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM