0

I want to mock/stub the async methods of the Connect class returned by websockets.client.connect; such as send and recv. I succeed in testing the instantiation of the class, but I can't seem to setup the methods?

The complete code is in this gist, but here are the main points:

This is how I'm preparing the mock:

        self.client_class_patcher = patch('websockets.client.connect')

        self.mock_connect_class = self.client_class_patcher.start()
        self.addCleanup(self.client_class_patcher.stop)

        self.connect_instance = MagicMock()
        self.connect_instance.send.side_effect = MagicMock(return_value="fake_result_data")
        self.connect_instance.recv.side_effect = MagicMock(return_value="fake_result_data")

        self.mock_connect_class.return_value = self.connect_instance

implementation code:

        async with websockets.client.connect(self.ws_url, subprotocols=["aop.ipc"], extra_headers="auth and things") as ws:
            await ws.send(json.dumps(call))
            response = await ws.recv()

In my tests:

    @async_test
    async def test_connection(self):
        # arrange
        _connector = MyRemoteDeviceClass("ws://nowhere:1234", "accesstoken")
        # act
        await _connector.enable_device("some_device_id")
        # assert
        self.mock_connect_class.assert_called_once_with("ws://nowhere:1234", subprotocols=["aop.ipc"], extra_headers=ANY) # this test is working fine :)
        self.connect_instance.recv.assert_called_once() #this test is not :(
        self.connect_instance.recv.assert_awaited_once() #neither is this

...of course, in real tests, we assert just one thing in each test :)

LFLFM
  • 790
  • 7
  • 16
  • 1
    Does this answer your question? [Python: Mocking a context manager](https://stackoverflow.com/questions/28850070/python-mocking-a-context-manager) In your case you would have to use the `__aenter__` coroutine method instead of `__enter__`. – Daniil Fajnberg May 02 '23 at 18:47
  • yes, that's it; thanks @DaniilFajnberg. I think this question might deserve its own answer though; as the async nature does add minor complications. Would you mind entering this in the form of an answer? I needed to fix the methods to use `AsyncMock()`, like this: `self.connect_instance.send = AsyncMock()` and the mocked instance to work with the context manager `self.mock_connect_class.return_value.__aenter__.return_value = self.connect_instance` – LFLFM May 03 '23 at 13:25

0 Answers0