This is in fact, working entirely as expected.
If we define a property that raises an AttributeError, then __getattr__() will be called, since the descriptor protocol says that an attribute error is a missing descriptor.
>>> class Foo(object):
... def __getattr__(self, attr):
... return 42
... @property
... def bacon(self):
... print(1)
... return int.lala
...
>>> Foo().bacon
1
42
If we then follow a similar pattern using mock:
>>> from unittest import mock
>>> a_mock = mock.MagicMock()
>>> def foo():
... print(1)
... raise AttributeError()
...
>>> no_attribute = mock.PropertyMock(side_effect=foo)
>>> type(a_mock).property = no_attribute
>>> a_mock.property
1
<MagicMock name='mock.property' id='139971099507232'>
You can see that the method is called, since we print one, but then what is going on is that MagicMock.__getattr__ is called, which has the behavior to return a new mock, like so:
>>> a_mock.b
<MagicMock name='mock.b' id='139971099646776'>

I could imagine doing some complex things to let you get at the AttributeError in this case but *not* when a different descriptor was added to type(a_mock), but I think it would confusing overall. This might be worth a doc tweak to cover it?