The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.

gRPC サービスの使用

gRPCクライアントは、アプリケーションコードにインジェクトすることができます。

gRPC サービスを消費するには、gRPC クラスを生成する必要があります。 proto ファイルを src/main/proto に置き、 mvn compile を実行してください。

スタブとインジェクション

gRPCの生成には、いくつかのスタブが用意されており、gRPCサービスを使用するためのさまざまな方法を提供しています。下記をインジェクトすることができます。

  • Mutiny APIを使用したサービスインターフェース

  • gRPC APIを使用したブロッキングスタブ

  • Mutinyをベースにしたリアクティブ・スタブ

  • 他のタイプのスタブを作成することができるgRPC io.grpc.Channel

import io.quarkus.grpc.GrpcClient;

import hello.Greeter;
import hello.GreeterGrpc.GreeterBlockingStub;
import hello.MutinyGreeterGrpc.MutinyGreeterStub;

class MyBean {

   // A service interface using the Mutiny API
   @GrpcClient("helloService")                   (1)
   Greeter greeter;

   // A reactive stub based on Mutiny
   @GrpcClient("helloService")
   MutinyGreeterGrpc.MutinyGreeterStub mutiny;

   // A blocking stub using the gRPC API
   @GrpcClient
   GreeterGrpc.GreeterBlockingStub helloService; (2)

   @GrpcClient("hello-service")
   Channel channel;

}
1 gRPCクライアントのインジェクションポイントには、 @GrpcClient の修飾子を付ける必要があります。この修飾子は、基礎となるgRPCクライアントの設定に使用される名前を指定するために使用できます。たとえば、この修飾子を hello-service に設定すると、サービスのホストの設定は、quarkus.grpc.clients.hello-service.host を使用して行われるようになります。
2 GrpcClient#value() で名前が指定されていない場合は、代わりにフィールド名が使用されます。例えば、この例では helloService です。

スタブクラス名は、 proto ファイルで使用されているサービス名に由来します。例えば、 Greeter をサービス名として使用している場合は以下のようになります。

option java_package = "hello";

service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

サービスインターフェース名は hello.Greeter 、Mutiny stub名は hello.MutinyGreeterGrpc.MutinyGreeterStub 、Blocking stub名は hello.GreeterGrpc.GreeterBlockingStub となります。

サービスインターフェース

import io.quarkus.grpc.GrpcClient;
import io.smallrye.mutiny.Uni;

import hello.Greeter;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/hello")
public class ExampleResource {

   @GrpcClient (1)
   Greeter hello;

   @GET
   @Path("/mutiny/{name}")
   public Uni<String> helloMutiny(String name) {
      return hello.sayHello(HelloRequest.newBuilder().setName(name).build())
            .onItem().transform(HelloReply::getMessage);
   }
}
1 サービス名はインジェクションポイントに由来する - フィールド名を使用しています。 quarkus.grpc.clients.hello.host プロパティの設定が必要です。

ブロッキングスタブ

import io.quarkus.grpc.GrpcClient;

import hello.GreeterGrpc.GreeterBlockingStub;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/hello")
public class ExampleResource {

   @GrpcClient("hello") (1)
   GreeterGrpc.GreeterBlockingStub blockingHelloService;

   @GET
   @Path("/blocking/{name}")
   public String helloBlocking(String name) {
      return blockingHelloService.sayHello(HelloRequest.newBuilder().setName(name).build()).getMessage();
   }
}
1 quarkus.grpc.clients.hello.host プロパティを設定する必要があります。

ストリームの取り扱い

gRPCでは、ストリームの送受信が可能です。

service Streaming {
    rpc Source(Empty) returns (stream Item) {} // Returns a stream
    rpc Sink(stream Item) returns (Empty) {}   // Reads a stream
    rpc Pipe(stream Item) returns (stream Item) {}  // Reads a streams and return a streams
}

Mutinyのスタブを使用すると、以下のようにこれらとやりとりすることができます。

package io.quarkus.grpc.example.streaming;

import io.grpc.examples.streaming.Empty;
import io.grpc.examples.streaming.Item;
import io.grpc.examples.streaming.MutinyStreamingGrpc;
import io.quarkus.grpc.GrpcClient;

import io.smallrye.mutiny.Multi;
import io.smallrye.mutiny.Uni;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/streaming")
@Produces(MediaType.APPLICATION_JSON)
public class StreamingEndpoint {

    @GrpcClient
    MutinyStreamingGrpc.MutinyStreamingStub streaming;

    @GET
    public Multi<String> invokeSource() {
        // Retrieve a stream
        return streaming.source(Empty.newBuilder().build())
                .onItem().transform(Item::getValue);
    }

    @GET
    @Path("sink/{max}")
    public Uni<Void> invokeSink(int max) {
        // Send a stream and wait for completion
        Multi<Item> inputs = Multi.createFrom().range(0, max)
                .map(i -> Integer.toString(i))
                .map(i -> Item.newBuilder().setValue(i).build());
        return streaming.sink(inputs).onItem().ignore().andContinueWithNull();
    }

    @GET
    @Path("/{max}")
    public Multi<String> invokePipe(int max) {
        // Send a stream and retrieve a stream
        Multi<Item> inputs = Multi.createFrom().range(0, max)
                .map(i -> Integer.toString(i))
                .map(i -> Item.newBuilder().setValue(i).build());
        return streaming.pipe(inputs).onItem().transform(Item::getValue);
    }

}

クライアント設定

アプリケーションにインジェクトする各gRPCサービスに対して、以下の属性を設定することができます。

ビルド時に固定される設定プロパティ - その他の設定プロパティは実行時にオーバーライド可能です。

Configures the gRPC clients

デフォルト

Use new Vert.x gRPC client support. By default, we still use previous Java gRPC support.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__USE_QUARKUS_GRPC_CLIENT

Show more

boolean

false

Explicitly enable use of XDS.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__XDS_ENABLED

Show more

boolean

false

Use secure credentials.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__XDS_SECURE

Show more

boolean

false

Optional explicit target.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__XDS_TARGET

Show more

string

Explicitly enable use of in-process.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__IN_PROCESS_ENABLED

Show more

boolean

false

Set in-process name.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__IN_PROCESS_NAME

Show more

string

quarkus-grpc

Number of threads on a delayed gRPC ClientCall

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__STORK_THREADS

Show more

int

10

Deadline in milliseconds of delayed gRPC call

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__STORK_DEADLINE

Show more

5000

Number of retries on a gRPC ClientCall

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__STORK_RETRIES

Show more

int

3

Initial delay in seconds on refresh check

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__STORK_DELAY

Show more

60

Refresh period in seconds

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__STORK_PERIOD

Show more

120

The gRPC service port.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__PORT

Show more

int

9000

The gRPC service test port.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__TEST_PORT

Show more

int

The host name / IP on which the service is exposed.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__HOST

Show more

string

localhost

The classpath path or file path to a server certificate or certificate chain in PEM format.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__SSL_CERTIFICATE

Show more

path

The classpath path or file path to the corresponding certificate private key file in PEM format.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__SSL_KEY

Show more

path

An optional trust store which holds the certificate information of the certificates to trust The trust store can be either on classpath or in an external file.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__SSL_TRUST_STORE

Show more

path

Use a name resolver. Defaults to dns. If set to "stork", host will be treated as SmallRye Stork service name

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__NAME_RESOLVER

Show more

string

dns

Whether plain-text should be used instead of TLS. Enabled by default, except if TLS/SSL is configured. In this case, plain-text is disabled.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__PLAIN_TEXT

Show more

boolean

The duration after which a keep alive ping is sent.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__KEEP_ALIVE_TIME

Show more

Duration

The flow control window in bytes. Default is 1MiB.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__FLOW_CONTROL_WINDOW

Show more

int

The duration without ongoing RPCs before going to idle mode.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__IDLE_TIMEOUT

Show more

Duration

The amount of time the sender of a keep alive ping waits for an acknowledgement.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__KEEP_ALIVE_TIMEOUT

Show more

Duration

Whether keep-alive will be performed when there are no outstanding RPC on a connection.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__KEEP_ALIVE_WITHOUT_CALLS

Show more

boolean

false

The max number of hedged attempts.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__MAX_HEDGED_ATTEMPTS

Show more

int

5

The max number of retry attempts. Retry must be explicitly enabled.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__MAX_RETRY_ATTEMPTS

Show more

int

5

The maximum number of channel trace events to keep in the tracer for each channel or sub-channel.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__MAX_TRACE_EVENTS

Show more

int

The maximum message size allowed for a single gRPC frame (in bytes). Default is 4 MiB.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__MAX_INBOUND_MESSAGE_SIZE

Show more

int

The maximum size of metadata allowed to be received (in bytes). Default is 8192B.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__MAX_INBOUND_METADATA_SIZE

Show more

int

The negotiation type for the HTTP/2 connection. Accepted values are: TLS, PLAINTEXT_UPGRADE, PLAINTEXT

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__NEGOTIATION_TYPE

Show more

string

TLS

Overrides the authority used with TLS and HTTP virtual hosting.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__OVERRIDE_AUTHORITY

Show more

string

The per RPC buffer limit in bytes used for retry.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__PER_RPC_BUFFER_LIMIT

Show more

Whether retry is enabled. Note that retry is disabled by default.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__RETRY

Show more

boolean

false

The retry buffer size in bytes.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__RETRY_BUFFER_SIZE

Show more

Use a custom user-agent.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__USER_AGENT

Show more

string

Use a custom load balancing policy. Accepted values are: pick_first, round_robin, grpclb. This value is ignored if name-resolver is set to 'stork'.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__LOAD_BALANCING_POLICY

Show more

string

pick_first

The compression to use for each call. The accepted values are gzip and identity.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__COMPRESSION

Show more

string

The deadline used for each call.

Environment variable: QUARKUS_GRPC_CLIENTS__CLIENT_NAME__DEADLINE

Show more

Duration

期間フォーマットについて

To write duration values, use the standard java.time.Duration format. See the Duration#parse() Java API documentation for more information.

数字で始まる簡略化した書式を使うこともできます:

  • 数値のみの場合は、秒単位の時間を表します。

  • 数値の後に ms が続く場合は、ミリ秒単位の時間を表します。

その他の場合は、簡略化されたフォーマットが解析のために java.time.Duration フォーマットに変換されます:

  • 数値の後に hms が続く場合は、その前に PT が付けられます。

  • 数値の後に d が続く場合は、その前に P が付けられます。

client-name は、 @GrpcClient で設定された名称、または明示的に定義されていない場合は、インジェクションポイントから派生した名称です。

以下の例では、クライアント名として _hello_を使用しています。 @GrpcClient アノテーションで使用した名前に置き換えることを忘れないでください。

quarkus.grpc.clients."client-name".use-quarkus-grpc-client を有効にすると、新しい Vert.x gRPC チャネル実装を使用することになるため、すべての設定プロパティを適用できるわけではありません。また、現在、Storkのサポートはまだありません。
quarkus.grpc.clients."client-name".xds.enabled を有効にすると、上記の設定のほとんどを処理するのはxDSになります。

TLSを有効にする

TLS を有効にするには、以下の設定を使用します。構成内のすべてのパスは、クラスパス上のリソース (通常は src/main/resources またはそのサブフォルダーから) または外部ファイルのいずれかを指定することに注意してください。

quarkus.grpc.clients.hello.host=localhost

# either a path to a classpath resource or to a file:
quarkus.grpc.clients.hello.ssl.trust-store=tls/ca.pem
SSL/TLSを設定すると、 plain-text は自動的に無効になります。

相互認証付きTLS

相互認証付きのTLSを使用するには、以下の設定を使用します。

quarkus.grpc.clients.hello.host=localhost
quarkus.grpc.clients.hello.plain-text=false

# all the following may use either a path to a classpath resource or to a file:
quarkus.grpc.clients.hello.ssl.certificate=tls/client.pem
quarkus.grpc.clients.hello.ssl.key=tls/client.key
quarkus.grpc.clients.hello.ssl.trust-store=tls/ca.pem

クライアント・スタブ・デッドライン

gRPCスタブにデッドラインを設定する必要がある場合、つまり、以後、スタブが常にステータスエラー DEADLINE_EXCEEDED を返すようになる期間を指定する必要がある場合、デッドラインは、 quarkus.grpc.clients."service-name".deadline の設定プロパティで指定することができます。例:

quarkus.grpc.clients.hello.host=localhost
quarkus.grpc.clients.hello.deadline=2s (1)
1 すべての注入されたスタブのデッドラインを設定します。
この機能を使用して、RPC タイムアウトを実装しないでください。RPC タイムアウトを実装するには、Mutiny call.ifNoItem().after(…​) または Fault Tolerance @Timeout のいずれかを使用してください。

gRPCヘッダー

HTTPと同様に、gRPCの呼び出しはメッセージと一緒にヘッダを運ぶことができます。 ヘッダは、例えば、認証のために有用です。

gRPCコールにヘッダを設定するには、ヘッダを付加したクライアントを作成し、このクライアントで呼び出しを実行します。

import jakarta.enterprise.context.ApplicationScoped;

import examples.Greeter;
import examples.HelloReply;
import examples.HelloRequest;
import io.grpc.Metadata;
import io.quarkus.grpc.GrpcClient;
import io.quarkus.grpc.GrpcClientUtils;
import io.smallrye.mutiny.Uni;

@ApplicationScoped
public class MyService {
    @GrpcClient
    Greeter client;

    public Uni<HelloReply> doTheCall() {
        Metadata extraHeaders = new Metadata();
        if (headers) {
            extraHeaders.put("my-header", "my-interface-value");
        }

        Greeter alteredClient = GrpcClientUtils.attachHeaders(client, extraHeaders); (1)

        return alteredClient.sayHello(HelloRequest.newBuilder().setName(name).build()); (2)
    }
}
1 extraHeaders を付加して呼び出しができるようにクライアントを変更します。
2 変更したクライアントで呼び出しを行います。オリジナルのクライアントは変更されないままです。

GrpcClientUtils は、あらゆる種類のクライアントに対応しています。

クライアントインターセプター

gRPCクライアントインターセプターは、 io.grpc.ClientInterceptor インターフェースも実装する CDI Bean で実装できます。インジェクトされたクライアントに @io.quarkus.grpc.RegisterClientInterceptor のアノテーションを付加することで、特定のクライアントインスタンスに対して指定されたインターセプターを登録できます。 @RegisterClientInterceptor のアノテーションは繰り返し使用できます。また、注入されたクライアントにインターセプターを適用したい場合は、インターセプターBeanに @io.quarkus.grpc.GlobalInterceptor のアノテーションを付けます。

グローバルクライアントインターセプターの例
import io.quarkus.grpc.GlobalInterceptor;

import io.grpc.ClientInterceptor;

@GlobalInterceptor (1)
@ApplicationScoped
public class MyInterceptor implements ClientInterceptor {

    @Override
    public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method,
            CallOptions callOptions, Channel next) {
       // ...
    }
}
1 このインターセプターは、インジェクトされたすべてのgRPCクライアントに適用されます。

プロデューサー・メソッドをグローバル・インターセプターとしてアノテーションすることも可能です:

import io.quarkus.grpc.GlobalInterceptor;

import jakarta.enterprise.inject.Produces;

public class MyProducer {
    @GlobalInterceptor
    @Produces
    public MyInterceptor myInterceptor() {
        return new MyInterceptor();
    }
}
ClientInterceptor JavaDoc をチェックして、インターセプターを適切に実装してください。
@RegisterClientInterceptor の例
import io.quarkus.grpc.GrpcClient;
import io.quarkus.grpc.RegisterClientInterceptor;

import hello.Greeter;

@ApplicationScoped
class MyBean {

    @RegisterClientInterceptor(MySpecialInterceptor.class) (1)
    @GrpcClient("helloService")
    Greeter greeter;
}
1 この特定のクライアントのために MySpecialInterceptor を登録します。

複数のクライアントインターセプターがある場合、 jakarta.enterprise.inject.spi.Prioritized インターフェースを実装することで、順番に並べることができます:

@ApplicationScoped
public class MyInterceptor implements ClientInterceptor, Prioritized {

    @Override
    public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method,
            CallOptions callOptions, Channel next) {
       // ...
    }

    @Override
    public int getPriority() {
        return 10;
    }
}

最高の優先度を持つインターセプターが最初に呼び出されます。インターセプターが Prioritized インターフェイスを実装していない場合に使用されるデフォルトの優先度は 0 です。

gRPCクライアントのメトリクス

メトリクス収集の有効化

gRPC クライアント・メトリクスは、アプリケーションもエクステンションを使用する場合に自動的に有効になります。 quarkus-micrometer エクステンションを使用している場合、gRPC クライアント・メトリクスは自動的に有効になります。micrometerは、アプリケーションが使用するすべてのgRPCクライアントのメトリクスを収集します。

例えば、メトリクスをPrometheusにエクスポートすると、以下のように取得できます。

# HELP grpc_client_responses_received_messages_total The total number of responses received
# TYPE grpc_client_responses_received_messages_total counter
grpc_client_responses_received_messages_total{method="SayHello",methodType="UNARY",service="helloworld.Greeter",} 6.0
# HELP grpc_client_requests_sent_messages_total The total number of requests sent
# TYPE grpc_client_requests_sent_messages_total counter
grpc_client_requests_sent_messages_total{method="SayHello",methodType="UNARY",service="helloworld.Greeter",} 6.0
# HELP grpc_client_processing_duration_seconds The total time taken for the client to complete the call, including network delay
# TYPE grpc_client_processing_duration_seconds summary
grpc_client_processing_duration_seconds_count{method="SayHello",methodType="UNARY",service="helloworld.Greeter",statusCode="OK",} 6.0
grpc_client_processing_duration_seconds_sum{method="SayHello",methodType="UNARY",service="helloworld.Greeter",statusCode="OK",} 0.167411625
# HELP grpc_client_processing_duration_seconds_max The total time taken for the client to complete the call, including network delay
# TYPE grpc_client_processing_duration_seconds_max gauge
grpc_client_processing_duration_seconds_max{method="SayHello",methodType="UNARY",service="helloworld.Greeter",statusCode="OK",} 0.136478028

サービス名、メソッド、タイプは tags で確認できます。

メトリクス収集の無効化

quarkus-micrometer を使用しているときに gRPC クライアントメトリクスを無効にするには、アプリケーションの設定に以下のプロパティを追加します。

quarkus.micrometer.binder.grpc-client.enabled=false

カスタム例外処理

gRPCサービスやサーバーインターセプターが(カスタム)例外を投げる場合、アプリケーションのCDI Beanとして独自の ExceptionHandlerProvider を追加し、これらの例外のカスタムハンドリングを提供することができます。

@ApplicationScoped
public class HelloExceptionHandlerProvider implements ExceptionHandlerProvider {
    @Override
    public <ReqT, RespT> ExceptionHandler<ReqT, RespT> createHandler(ServerCall.Listener<ReqT> listener,
            ServerCall<ReqT, RespT> serverCall, Metadata metadata) {
        return new HelloExceptionHandler<>(listener, serverCall, metadata);
    }

    @Override
    public Throwable transform(Throwable t) {
        if (t instanceof HelloException he) {
            return new StatusRuntimeException(Status.ABORTED.withDescription(he.getName()));
        } else {
            return ExceptionHandlerProvider.toStatusException(t, true);
        }
    }

    private static class HelloExceptionHandler<A, B> extends ExceptionHandler<A, B> {
        public HelloExceptionHandler(ServerCall.Listener<A> listener, ServerCall<A, B> call, Metadata metadata) {
            super(listener, call, metadata);
        }

        @Override
        protected void handleException(Throwable t, ServerCall<A, B> call, Metadata metadata) {
            StatusRuntimeException sre = (StatusRuntimeException) ExceptionHandlerProvider.toStatusException(t, true);
            Metadata trailers = sre.getTrailers() != null ? sre.getTrailers() : metadata;
            call.close(sre.getStatus(), trailers);
        }
    }
}

Devモード

デフォルトでは、devモードでアプリケーションを起動すると、サービスが設定されていない場合でもgRPCサーバが起動します。 gRPCエクステンションのDevモードの動作は、以下のプロパティで設定することができます。

ビルド時に固定される設定プロパティ - その他の設定プロパティは実行時にオーバーライド可能です。

Configuration property

デフォルト

Start gRPC server in dev mode even if no gRPC services are implemented. By default set to true to ease incremental development of new services using dev mode.

Environment variable: QUARKUS_GRPC_DEV_MODE_FORCE_SERVER_START

Show more

boolean

true

モッククライアントの注入

@QuarkusTest では、 @InjectMock を使用して、gRPC サービスの Mutiny クライアントを注入できます:

@QuarkusTest
public class GrpcMockTest {

    @InjectMock
    @GrpcClient("hello")
    Greeter greeter;

    @Test
    void test1() {
        HelloRequest request = HelloRequest.newBuilder().setName("neo").build();
        Mockito.when(greeter.sayHello(Mockito.any(HelloRequest.class)))
                .thenReturn(Uni.createFrom().item(HelloReply.newBuilder().setMessage("hello neo").build()));
        Assertions.assertEquals(greeter.sayHello(request).await().indefinitely().getMessage(), "hello neo");
    }
}
モック できるのはMutinyクライアントのみで、チャンネルや、その他のスタブはモックできません。

関連コンテンツ