classification
Title: Mock.assert_has_calls works strange
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.10
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: cjw296, corona10, dmitriy.mironiyk, kamilturek, lisroach, mariocj89, michael.foord, xtreak
Priority: normal Keywords:

Created on 2021-03-02 14:31 by dmitriy.mironiyk, last changed 2021-03-15 18:47 by xtreak.

Files
File name Uploaded Description Edit
test_mock_asser_has_calls.py dmitriy.mironiyk, 2021-03-02 14:31
Messages (2)
msg387932 - (view) Author: Dmitriy Mironiyk (dmitriy.mironiyk) Date: 2021-03-02 14:31
I think that behavior of Mock.assert_has_calls is misleading. 
- When I call Mock.assert_has_calls with any_order=False it checks that expected calls are the same calls as performed on mock and raise an error if mock has some calls other than expected.
- When I call Mock.assert_has_calls with any_order=True it checks that mock has expected calls and not raise an error when mock has other calls than expected.

I suppose should be two separate methods:
- Mock.assert_has_only_calls that always raise an error when mock has calls other than expected(not regarding any_order).
- Mock.assert_has_calls that raise error only when no calls that provided in expected or if order of calls is wrong when any_order=False.
msg388758 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python committer) Date: 2021-03-15 18:47
https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_has_calls

> If any_order is false then the calls must be sequential. There can be extra calls before or after the specified calls.

One way to check that the calls appear in order even with extra calls in between since any_order=False expects the calls to be sequential is to use mock_calls which is a list and use index method. It's not very elegant.

>>> from unittest.mock import Mock, call
>>> m = Mock()
>>> m(1)
<Mock name='mock()' id='139845749964176'>
>>> m(2)
<Mock name='mock()' id='139845749964176'>
>>> m(3)
<Mock name='mock()' id='139845749964176'> 
>>> m.mock_calls.index(call(1))
0
>>> m.mock_calls.index(call(3))
2

> - Mock.assert_has_only_calls that always raise an error when mock has calls other than expected(not regarding any_order).

This sounds like a stricter version of assert_has_calls to ensure expected is matched without order with mock_calls and len(expected) == len(mock_calls)

I am not keen on changing behavior of assert_has_calls with any additional flags for compatibility but any additional helper should go in python 3.10 only. So I have updated the version.
History
Date User Action Args
2021-03-15 18:47:49xtreaksetversions: + Python 3.10, - Python 3.7
nosy: + cjw296, michael.foord, lisroach, mariocj89

messages: + msg388758

components: + Library (Lib), - Tests
2021-03-03 21:19:04kamiltureksetnosy: + kamilturek
2021-03-03 04:07:07corona10setnosy: + corona10
2021-03-03 03:14:51xtreaksetnosy: + xtreak
2021-03-02 14:31:34dmitriy.mironiykcreate