0

Following the suggestions in this question I was able to unit test the synchronous methods of my gRPC service (which is built with the grpc.aio API) using the grpc_testing library. However, when I follow this example on an asynchronous method of my gRPC service I get:

ERROR    grpc_testing._server._rpc:_rpc.py:92 Exception calling application!
Traceback (most recent call last):
  File "/home/jp/venvs/grpc/lib/python3.8/site-packages/grpc_testing/_server/_service.py", line 63, in _stream_response
    response = copy.deepcopy(next(response_iterator))
TypeError: 'async_generator' object is not an iterator

Looking through the grpc_testing codebase and searching more broadly, I cannot find examples of unit testing async gRPC methods. The closest thing I could find is an unmerged branch of pytest-grpc, but the example service does not have any async methods.

Can anyone share an example of unit testing an asynchronous gRPC method in python?

  • I have come up with an answer with the simplest settings [How to do unit tests on python async functions?](https://stackoverflow.com/questions/68410035/how-to-do-unit-tests-on-python-async-functions?) – George Y Jul 17 '21 at 02:51

3 Answers3

3

I followed @Lidi's recommendations (thank you) and implemented the tests using pytest-asyncio. For what it's worth, here is a basic example testing an async stream stream method:

import mock
import grpc
import pytest

from tokenize_pb2 import MyMessage
from my_implementation import MyService

async def my_message_generator(messages):
    for message in messages:
        yield message

@pytest.mark.asyncio
async def test_my_async_stream_stream_method():
    service = MyService()
    my_messages = my_message_generator([MyMessage(), MyMessage()])
    mock_context = mock.create_autospec(spec=grpc.aio.ServicerContext)
    response = service.MyStreamStreamMethod(my_messages, mock_context)
    results = [x async for x in response]
    assert results == expected_results
1

gRPC Testing is a nice project. But we need engineering resources to make it support asyncio, and mostly importantly, adopt the existing APIs to asyncio's philosophy.

For testing gRPC asyncio, I would recommend just use pytest which has pytest-asyncio to smoothly test out asyncio features. Here is an example: code.

Lidi Zheng
  • 1,801
  • 8
  • 13
1

The solution given in Joshua's answer also works with python unittest framework utilizing the unittest.IsolatedAsyncioTestCase class. For example:

import mock
import grpc
import unittest

from example_pb2 import MyRequestMessage
from my_implementation import MyService

class Tests(unittest.IsolatedAsyncioTestCase):

    def setUp(self):
        self.service = MyService()
        self.mock_context = mock.create_autospec(spec=grpc.aio.ServicerContext)

    async def test_subscribe_unary_stream(self):
        response = self.service.MyUnaryStreamMethod(MyRequestMessage(), self.mock_context)
        async for result in response:
            self.assertIsNotNone(result)

While this allows testing of the actual business logic in the RPC functions, it falls short of grpcio-testing in terms of service features like response codes, timeouts etc.

jobobo2000
  • 11
  • 2