irmen / Pyro5

Pyro 5 - Python remote objects
https://pyro5.readthedocs.io
MIT License
303 stars 36 forks source link

Unable to mock exposed method #91

Closed MariusGailius closed 3 months ago

MariusGailius commented 4 months ago

I am trying to mock exposed method and get: remote object 'PYRO:TestClass@127.0.0.1:60000' has no exposed attribute 'method_i_would_like_to_mock'. Is there anyway around this? Assuming this happens because of Pyro5 magic. I only need to mock one of the exposed methods while preserving other methods. Sample server:

"""Dummy client to reproduce mock issue"""

import Pyro5.api

@Pyro5.api.expose
class TestClass:
    """Dummy class to reproduce mock issue"""

    def __init__(self) -> None:
        pass

    def method_i_would_like_to_mock(self) -> int:
        """I would like to mock this method"""
        return 1

    def other_method_no_one_cares_about(self) -> int:
        """Do not care about this one"""
        return 2

if __name__ == "__main__":

    Pyro5.server.serve(
        {
            TestClass(): "TestClass",
        },
        host="127.0.0.1",
        port=60000,
        use_ns=False,
    )

Sample client:

"""Dummy client to reproduce mock issue"""

from unittest.mock import Mock
import Pyro5.api
import Pyro5.errors

if __name__ == "__main__":
    remote = Pyro5.api.Proxy("PYRO:TestClass@127.0.0.1:60000")
    # pylint: disable-next=protected-access
    remote._pyroBind()  # force to establish communication now
    print(remote.method_i_would_like_to_mock)
    print(remote.method_i_would_like_to_mock())
    remote.method_i_would_like_to_mock = Mock()
    print("yay!")

Using python 3.12.1.

Thanks, Marius

MariusGailius commented 4 months ago

To clarify - I need to mock only one method, others should behave the same.

MariusGailius commented 3 months ago

Ended up making a custom proxy object that passes function calls to pyro and mocks what I need. Not elegant, but works.

irmen commented 3 months ago

Yeah you probably chose the easiest workaround.

Attributes on Pyro proxy objects are intercepted because they need to set/retrieve the value on the remote object.