'Is there a way to use "assert_called_with" that only checks specific word?

I am trying to use assert_called_with to assert the argument that is passed to the mocked object. There is only one argument of that function but the argument is very large. {"A":{"B": {"C" : {"D": {"key": "keyword", "any": "aaa", "anything": "bbbb"}}}}

I only care about "key": "keyword" exists and do not care about other stuff, is there a way to do so?



Solution 1:[1]

Assuming that your function has one argument, that is a nested dictionary and shall on some level contain the specific key/value pair, you have to iterate over that dictionary manually using some function.

You get the arguments of all calls of your mocked function from call_args_list. Each entry contains a tuple with the list of positional arguments and the keyword arguments, e.g. call_args_list[0][0][0] contains the first positional argument of the first call.

Assuming that your tested function have always exactly one arguments, that is called as a positional argument, you can do something like this:

def dict_contains_key_value(arg, key, value):
    if not isinstance(arg, dict):
        return False
    for k, v in arg.items():
        if k == key and v == value:
            return True
        if dict_contains_key_value(v, key, value):
            return True
    return False


@mock.patch("my_module.sut")
def test_called_arg(mocked):
    caller()  # the function that calls `sut()` several times
    mocked.assert_called()
    assert any(dict_contains_key_value(args[0][0], "key", "keyword")
               for args in mocked.call_args_list)

A few notes:

  • if you are not sure that the function has always an argument, you have to add a check (e.g. for args[0])
  • if the argument can also be called as a keyword argument, you have to expand the check (args[1] would give you the dictionary of keyword arguments)
  • the function dict_contains_key_value can be optimized and extended if needed, this is just a simple example

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 MrBean Bremen