2Mocks for the gRPC servers. 
    4@sa @ref scripts/docs/en/userver/tutorial/grpc_service.md 
   11from typing 
import Callable
 
   12from typing 
import List
 
   13from typing 
import Optional
 
   18from testsuite.utils 
import callinfo
 
   24    def __init__(self, servicer, methods):
 
   29    def get(self, method, default):
 
   30        return self.
_methods.get(method, default)
 
   32    def reset_handlers(self):
 
   35    @contextlib.contextmanager 
   42    def install_handler(self, method: str):
 
   46                    f
'Trying to mock unknown grpc method {method}',
 
   49            wrapped = callinfo.acallqueue(func)
 
   56@pytest.fixture(scope='session') 
 
   59    Returns the gRPC endpoint to start the mocking server that is set by 
   60    command line `--grpc-mockserver-host` and `--grpc-mockserver-port` options. 
   62    For port 0, picks some free port. 
   64    Override this fixture to customize the endpoint used by gRPC mockserver. 
   66    @snippet samples/grpc_service/tests/conftest.py  Prepare configs 
   67    @ingroup userver_testsuite_fixtures 
   69    port = pytestconfig.option.grpc_mockserver_port
 
   70    if pytestconfig.option.service_wait 
or pytestconfig.option.service_disable:
 
   71        port = port 
or DEFAULT_PORT
 
   73        port = get_free_port()
 
   74    return f
'{pytestconfig.option.grpc_mockserver_host}:{port}' 
   77@pytest.fixture(scope='session') 
 
   80    Returns the gRPC mocking server. 
   82    @snippet samples/grpc_service/tests/conftest.py  Prepare server mock 
   83    @ingroup userver_testsuite_fixtures 
   85    server = grpc.aio.server()
 
   86    server.add_insecure_port(grpc_mockserver_endpoint)
 
   87    server_task = asyncio.create_task(server.start())
 
   92        await asyncio.shield(server.stop(grace=
None))
 
   93        await asyncio.shield(server.wait_for_termination())
 
   94        await asyncio.shield(server_task)
 
   97@pytest.fixture(scope='session') 
 
  100    Creates the gRPC mock server for the provided type. 
  102    @snippet samples/grpc_service/tests/conftest.py  Prepare server mock 
  103    @ingroup userver_testsuite_fixtures 
  105    return _create_servicer_mock
 
 
  108def pytest_addoption(parser):
 
  109    group = parser.getgroup(
'grpc-mockserver')
 
  111        '--grpc-mockserver-host',
 
  113        help=
'gRPC mockserver hostname, default is [::]',
 
  116        '--grpc-mockserver-port',
 
  119        help=
'gRPC mockserver port, by default random port is used',
 
  123def _create_servicer_mock(
 
  124        servicer_class: type,
 
  126        stream_method_names: Optional[List[str]] = 
None,
 
  127        before_call_hook: Optional[Callable[..., 
None]] = 
None,
 
  129    def wrap_grpc_method(name, default_method, is_stream):
 
  130        @functools.wraps(default_method) 
  131        async def run_method(self, *args, **kwargs):
 
  132            if before_call_hook 
is not None:
 
  133                before_call_hook(*args, **kwargs)
 
  135            method = mock.get(name, 
None)
 
  136            if method 
is not None:
 
  137                call = method(*args, **kwargs)
 
  139                call = default_method(self, *args, **kwargs)
 
  143        @functools.wraps(default_method) 
  144        async def run_stream_method(self, *args, **kwargs):
 
  145            if before_call_hook 
is not None:
 
  146                before_call_hook(*args, **kwargs)
 
  148            method = mock.get(name, 
None)
 
  149            async for response 
in await method(*args, **kwargs):
 
  152        return run_stream_method 
if is_stream 
else run_method
 
  155    for attname, value 
in servicer_class.__dict__.items():
 
  157            methods[attname] = wrap_grpc_method(
 
  159                default_method=value,
 
  160                is_stream=attname 
in (stream_method_names 
or []),
 
  163    mocked_servicer_class = type(
 
  164        f
'Mock{servicer_class.__name__}', (servicer_class,), methods,
 
  166    servicer = mocked_servicer_class()