What steps will reproduce the problem? 1. class Foo(Mock): pass 2. f = Foo() print type(f.bar.baz)
What is the expected output? What do you see instead?
expected: <class 'Mock'>
instead: <class 'mock.Foo'> (interesting aside - the class name isn't even correct!)
What version of the product are you using? On what operating system?
>>> print mock.version 0.7.2
Please provide any additional information below.
This is particularly problematic when you want to add some functionality to a mock, but that functionality is not appropriate (and causes errors) when applied to its attributes. In my case, I'm defining an adapter (http://twistedmatrix.com/documents/11.0.0/api/twisted.python.components.html) for my subclass, but properties of its instances should not be adaptable.
Comment #1
Posted on Jul 18, 2011 by Helpful MonkeyInteresting.
Ensuring that mock attributes are of the same type as the parent was a deliberate decision. If you create a subclass of Mock with helper methods then having those available on all attributes is very useful. This is an unfortunate side effect of that decision.
I'll see if I can find a way to get the best of both worlds (probably a method for subclasses to override to prevent attributes using the parent class).
Comment #2
Posted on Jul 18, 2011 by Helpful MonkeyAnd as a note the name of the class is not incorrect. Working out why is left as an exercise for the reader... :-)
It's likely that any fix for this issue will be in 0.8 rather than a new 0.7 release, because I'll probably fix it with a new feature rather than reverting the attribute / subclass interaction.
Comment #3
Posted on Jul 18, 2011 by Helpful MonkeyActually, you can already achieve this by overriding _get_child_mock
:
{{{
class Subclass(Mock): def _get_child_mock(self, **kwargs): return MagicMock(**kwargs)
{{{
This will be used for return value and attributes. I'll add a test for this so that I don't break it in the future and add it as an example to the docs.
Comment #4
Posted on Jul 18, 2011 by Happy LionThat's what I've done (overriding _get_child_mock), but that leading underscore suggests it's not the best solution. Maybe just making that method public (or renaming) would fix this?
Comment #5
Posted on Jul 18, 2011 by Helpful MonkeyIt's not a straightforward situation though - making it a public api would imply you could call it directly. Which you shouldn't. I think documenting it as the right way to solve this particular problem is the best approach.
See:
http://www.voidspace.org.uk/python/weblog/arch_d7_2011_07_16.shtml#e1221
This will be in the mock examples page from the 0.8 release.
For what its worth this is an api issue I've come across several times before - how to make it clear that a method is not part of the external public api but can be overridden by subclasses.
Status: WontFix
Labels:
Type-Enhancement
Priority-Medium