Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to assert method call order with Python Mock?

Tags:

python

mocking

Suppose I have a python function

def func(self):
    self.method_1()
    self.method_2()

How can I write an unit test that can assert method_1 is called before method_2?

@mock.patch(method_1)
@mock.patch(method_2)
def test_call_order(method_2_mock, method_1_mock):
     # Test the order
like image 811
Kintarō Avatar asked Sep 08 '15 16:09

Kintarō


Video Answer


2 Answers

Another option is to create a simple list and append each mock to it through side_effect.

@mock.patch(method_1)
@mock.patch(method_2)
def test_call_order(method_2_mock, method_1_mock):
    call_order = []
    method_1_mock.side_effect = lambda *a, **kw: call_order.append(method_1_mock)
    method_2_mock.side_effect = lambda *a, **kw: call_order.append(method_2_mock)
    # Run test code...
    assert call_order == [method_1_mock, method_2_mock]

Each time the method is called, the side_effect lambda function is called. Since lists are ordered, this is a clean way to check the call order of your methods.

like image 81
Chris Collett Avatar answered Nov 15 '22 18:11

Chris Collett


Your case is a slight variation of Python Unit Testing with two mock objects, how to verify call-order?. What you should do is set method_2_mock, method_1_mock as children of one new mock object and then ask for mock_calls attribute or use assert_has_calls:

@mock.patch(method_1)
@mock.patch(method_2)
def test_call_order(method_2_mock, method_1_mock):
    mock_parent = Mock()
    mock_parent.m1, mock_parent.m2 = method_1_mock, method_2_mock
    <test code>
    """Check if method 1 is called before method 2"""
    mock_parent.assert_has_calls([call.m1(), call.m2()])

There are lot of details omitted in this code like call arguments. Take a look to call and the very useful ANY helper.

ATTENTION This is valid just for unitetest.mock in python3. For python 2.7 and mock 1.0.1 you should use attach_mock instead.

like image 23
Michele d'Amico Avatar answered Nov 15 '22 16:11

Michele d'Amico