Когда я вызываю mock.patch, я ожидаю, что он заменит тип. Я заменяю тип, который я предоставил, используя новый аргумент ключевого слова.
It does not replace the type, но он возвращает правильный объект, когда вызывается patch.start()
.
FakesPatcher
- это хак, который заставляет старый объект создавать новый объект. Он работает для Python 3.x и PyPy. Однако it doesn't work for Python 2.x. (см. Ниже).
Я хочу, чтобы FakesPatcher
ушел в любом случае и вместо этого использовал mock.patch
.Патч не заменяет целевой объект, но возвращает его правильно
Что я делаю неправильно здесь и как я могу это исправить?
def substitute(obj, qualified_name, spec):
testdouble = mock.patch(qualified_name, spec=spec, spec_set=True, new=obj)
testdouble.attribute_name = qualified_name # Forces patch to use the extra patcher
class FakesPatcher(object):
"""Ugly hack."""
new = 1
def _new(*args, **kwargs):
return obj.__new__(obj)
def __enter__(self):
self._old_new = spec.__new__
spec.__new__ = self._new
return obj
def __exit__(self, exc_type, exc_val, exc_tb):
spec.__new__ = self._old_new
testdouble.additional_patchers.append(FakesPatcher())
return testdouble
def fake(obj):
"""
:rtype : mock._patch
:param obj:
"""
try:
configuration = obj.Configuration()
except AttributeError:
raise TypeError('A fake testdouble must have a Configuration class.')
try:
spec = configuration.spec
except AttributeError:
raise TestDoubleConfigurationError('The type to be faked was not specified.')
qualified_name = get_qualified_name(spec)
attrs = dict(obj.__dict__)
attrs.pop('Configuration')
methods = get_missing_methods(spec, obj)
for method in methods:
def make_default_implementation(attr):
def default_implementation(*args, **kwargs):
raise NotImplementedError('%s was not implemented when the object was faked.' % attr)
return default_implementation
attrs.update({method: make_default_implementation(method)})
properties = get_missing_properties(spec, obj)
for prop in properties:
def make_default_implementation(attr):
def default_implementation(*args, **kwargs):
raise NotImplementedError('%s was not implemented when the object was faked.' % attr)
return property(fget=lambda *args, **kwargs: default_implementation(*args, **kwargs),
fset=lambda *args, **kwargs: default_implementation(*args, **kwargs),
fdel=lambda *args, **kwargs: default_implementation(*args, **kwargs))
attrs.update({prop: make_default_implementation(prop)})
fake_qualified_name = get_qualified_name(obj)
obj = type(obj.__name__, obj.__bases__, attrs)
return substitute(obj, qualified_name, spec)
В случае, если вы хотите играть с кодом и проверить его, вы можете найти его here.
EDIT:
I solved ошибки Python 2.x путем замены лямбда методом экземпляра.
Что делать, если я заменяю его по всему миру? –