mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 05:31:20 +00:00 
			
		
		
		
	bpo-36871: Ensure method signature is used when asserting mock calls to a method (GH13261)
* Fix call_matcher for mock when using methods * Add NEWS entry * Use None check and convert doctest to unittest * Use better name for mock in tests. Handle _SpecState when the attribute was not accessed and add tests. * Use reset_mock instead of reinitialization. Change inner class constructor signature for check * Reword comment regarding call object lookup logic
This commit is contained in:
		
							parent
							
								
									03acba6f1a
								
							
						
					
					
						commit
						c96127821e
					
				
					 3 changed files with 86 additions and 1 deletions
				
			
		|  | @ -804,6 +804,35 @@ def _format_mock_failure_message(self, args, kwargs, action='call'): | |||
|         return message % (action, expected_string, actual_string) | ||||
| 
 | ||||
| 
 | ||||
|     def _get_call_signature_from_name(self, name): | ||||
|         """ | ||||
|         * If call objects are asserted against a method/function like obj.meth1 | ||||
|         then there could be no name for the call object to lookup. Hence just | ||||
|         return the spec_signature of the method/function being asserted against. | ||||
|         * If the name is not empty then remove () and split by '.' to get | ||||
|         list of names to iterate through the children until a potential | ||||
|         match is found. A child mock is created only during attribute access | ||||
|         so if we get a _SpecState then no attributes of the spec were accessed | ||||
|         and can be safely exited. | ||||
|         """ | ||||
|         if not name: | ||||
|             return self._spec_signature | ||||
| 
 | ||||
|         sig = None | ||||
|         names = name.replace('()', '').split('.') | ||||
|         children = self._mock_children | ||||
| 
 | ||||
|         for name in names: | ||||
|             child = children.get(name) | ||||
|             if child is None or isinstance(child, _SpecState): | ||||
|                 break | ||||
|             else: | ||||
|                 children = child._mock_children | ||||
|                 sig = child._spec_signature | ||||
| 
 | ||||
|         return sig | ||||
| 
 | ||||
| 
 | ||||
|     def _call_matcher(self, _call): | ||||
|         """ | ||||
|         Given a call (or simply an (args, kwargs) tuple), return a | ||||
|  | @ -811,7 +840,12 @@ def _call_matcher(self, _call): | |||
|         This is a best effort method which relies on the spec's signature, | ||||
|         if available, or falls back on the arguments themselves. | ||||
|         """ | ||||
|         sig = self._spec_signature | ||||
| 
 | ||||
|         if isinstance(_call, tuple) and len(_call) > 2: | ||||
|             sig = self._get_call_signature_from_name(_call[0]) | ||||
|         else: | ||||
|             sig = self._spec_signature | ||||
| 
 | ||||
|         if sig is not None: | ||||
|             if len(_call) == 2: | ||||
|                 name = '' | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Xtreak
						Xtreak