How to test .__ getitem __ () call in Mock mock_calls list during unit testing

When trying to unit test a method that returns a tuple, and I try to check if the code accesses the correct tuple index, python tries to evaluate the expected call and turns it into a string.

call().methodA().__getitem__(0) ends up converting to '().methodA' in my expected_calls list for approval.

The above code example gives the result and trace:

 expected_calls=[call().methodA(), '().methodA'] result_calls=[call().methodA(), call().methodA().__getitem__(0)] ====================================================================== ERROR: test_methodB (badMockCalls.Test_UsingToBeMocked_methods) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\dev\workspace\TestCode\src\badMockCalls.py", line 43, in test_methodB self.assertListEqual(expected_calls, self.result_calls) File "C:\Python33\lib\unittest\case.py", line 844, in assertListEqual self.assertSequenceEqual(list1, list2, msg, seq_type=list) File "C:\Python33\lib\unittest\case.py", line 764, in assertSequenceEqual if seq1 == seq2: File "C:\Python33\lib\unittest\mock.py", line 1927, in __eq__ first, second = other ValueError: too many values to unpack (expected 2) ---------------------------------------------------------------------- Ran 1 test in 0.006s FAILED (errors=1) 

How can I state that method B calls self.tbm.methodA () [0] correctly?

Sample code (Python 3.3.2):

 import unittest from unittest.mock import call, patch import logging log = logging.getLogger(__name__) log.setLevel(logging.DEBUG) _ch = logging.StreamHandler() _ch.setLevel(logging.DEBUG) log.addHandler(_ch) class ToBeMocked(): # external resource that can't be changed def methodA(self): return (1,) class UsingToBeMocked(): # project code def __init__(self): self.tbm = ToBeMocked() def methodB(self): value = self.tbm.methodA()[0] return value class Test_UsingToBeMocked_methods(unittest.TestCase): def setUp(self): self.patcher = patch(__name__ + '.ToBeMocked') self.mock_ToBeMocked = self.patcher.start() self.utbm = UsingToBeMocked() # clear out the mock_calls list from the constructor calls self.mock_ToBeMocked.mock_calls = [] # set result to always point to the mock_calls that we are testing self.result_calls = self.mock_ToBeMocked.mock_calls def tearDown(self): self.patcher.stop() def test_methodB(self): self.utbm.methodB() # make sure the correct sequence of calls is made with correct parameters expected_calls = [call().methodA(), call().methodA().__getitem__(0)] log.debug('expected_calls=' + str(expected_calls)) log.debug(' result_calls=' + str(self.result_calls)) self.assertListEqual(expected_calls, self.result_calls) if __name__ == "__main__": unittest.main() 
+8
python unit-testing mocking automated-tests
source share
2 answers

Check mock_object.account['xxx1'].patch(body={'status': 'active'}) I had to use a test:

 mock_object.account.__getitem__.assert_has_calls([ call('xxxx1'), call().patch(body={'status': 'active'}), ]) 

I can’t explain why this works, it looks like weird behavior, maybe a layout error, but I consistently get these results and it works.

+3
source share

I just stumbled upon the same problem. I used the / work -around solution from here:

http://www.voidspace.org.uk/python/mock/examples.html#mocking-a-dictionary-with-magicmock

namely:

 >> mock.__getitem__.call_args_list [call('a'), call('c'), call('d'), call('b'), call('d')] 

You can skip the misinterpretation of the name of the magic function and check its arguments.

+1
source share

All Articles