def runs(self, function=None): """Gives a function to run instead of the mocked out one. Args: - function: callable (defaults to function being replaced) Returns: - self, i.e. can be chained with other Expectation methods """ if [val for _, val in self._action.items() if val]: self.__raise(FlexError, 'runs() cannot be mixed with return values') if not function: function = self.original_method replace_with = self._replace_with original_method = self.original_method if replace_with: self.__raise(FlexError, 'runs() cannot be specified twice') obj = self.mock._Flex__object func_type = type(function) if _isclass(obj): if func_type is not classmethod and func_type is not staticmethod: self.__raise( FlexError, 'calls() cannot be used on a class mock') if function == original_method: self._pass_thru = True self._replace_with = function return self
def __getattribute__(self, name): # TODO(herman): this sucks, generalize this! if name == '__new__': if _isclass(self.__object): raise AttributeError else: raise FlexError('__new__ can only be replaced on classes') return object.__getattribute__(self, name)
def pass_thru(expectation, *kargs, **kwargs): return_values = None original_method = expectation.original_method mock = expectation.mock obj = mock._Flex__object if _isclass(obj): if (type(original_method) is classmethod or type(original_method) is staticmethod): original = expectation.original_function return_values = original(*kargs, **kwargs) else: return_values = original_method(*kargs, **kwargs) return return_values
def mock_method(runtime_self, *kargs, **kwargs): arguments = {'kargs': kargs, 'kwargs': kwargs} expectation = self.__get_expectation(method, arguments) if expectation: if not expectation._runnable(): raise StateError( '%s expected to be called when %s is True' % (method, _get_runnable_name(expectation._runnable))) expectation._times_called += 1 expectation._verify(final=False) _pass_thru = expectation._pass_thru _replace_with = expectation._replace_with if _pass_thru: return pass_thru(expectation, *kargs, **kwargs) elif _replace_with: return _replace_with(*kargs, **kwargs) yield_values = expectation._action['yield_values'] return_values = expectation._action['return_values'] if yield_values: return generator_method(yield_values) elif return_values: return_value = return_values[0] del return_values[0] return_values.append(return_value) else: return_value = ReturnValue() if return_value.raises: if _isclass(return_value.raises): raise return_value.raises( *return_value.value['kargs'], **return_value.value['kwargs']) else: raise return_value.raises else: return return_value.value else: # make sure to clean up expectations to ensure none of them # interfere with the runner's error reporing mechanism # e.g. open() for mock_object, expectations in _flex_objects.items(): for expectation in expectations: expectation._reset() raise MethodSignatureError(_format_args(method, arguments))
def __stubs(self, method): """Replaces a method with a fake one. Args: - method: string name of the method to stub Returns: - Expectation object """ obj = self.__object return_value = None if (method.startswith('__') and not method.endswith('__') and not inspect.ismodule(obj)): if _isclass(obj): name = obj.__name__ else: name = obj.__class__.__name__ method = '_%s__%s' % (name.lstrip('_'), method.lstrip('_')) if not isinstance(obj, _Flex) and not hasattr(obj, method): raise FlexError('%s does not have method %s' % (obj, method)) if self not in _flex_objects: _flex_objects[self] = [] expectation = self.__create_expectation(method, return_value) if expectation not in _flex_objects[self]: try: self.__update_method(expectation, method) _flex_objects[self].append(expectation) except TypeError: raise MockBuiltinError( 'Python does not allow updating builtin objects. ' 'Consider wrapping it in a class you can mock instead') except AttributeError: raise MockBuiltinError( 'Python does not allow updating instances of builtins. ' 'Consider wrapping it in a class you can mock instead') return expectation