events
ASP.NET Core で gRPC サービスをテストする
注意
これは、この記事の最新バージョンではありません。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
警告
このバージョンの ASP.NET Core はサポート対象から除外されました。 詳細については、 .NET および .NET Core サポート ポリシーを参照してください。 現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
重要
この情報はリリース前の製品に関する事項であり、正式版がリリースされるまでに大幅に変更される可能性があります。 Microsoft はここに示されている情報について、明示か黙示かを問わず、一切保証しません。
現在のリリースについては、この記事の .NET 9 バージョンを参照してください。
作成者: James Newton-King
テストは、安定し、保守性に優れたソフトウェアを構築する上で重要な作業です。 この記事では、ASP.NET Core の gRPC サービスをテストする方法について説明します。
gRPC サービスをテストする場合、3 つの一般的な方法があります。
- 単体テスト: 単体テスト ライブラリから gRPC サービスを直接テストします。
- 統合テスト: gRPC アプリは、
Microsoft.AspNetCore.TestHost
パッケージのメモリ内テスト サーバーである TestServer でホストされています。 gRPC サービスは、単体テスト ライブラリの gRPC クライアントを使用して呼び出すことでテストされます。 - 手動テスト: アドホック呼び出しで gRPC サーバーをテストします。 gRPC サービスでコマンドラインおよび UI ツールを使用する方法については、「ASP.NET Core で gRPCurl と gRPCui を使用して gRPC サービスをテストする」を参照してください。
単体テストでは、gRPC サービスだけが関与します。 サービスに挿入される依存関係はモックする必要があります。 統合テストでは、gRPC サービスとその補助インフラストラクチャがテストに含まれます。 これには、アプリの起動、依存関係の挿入、ルーティングと認証、承認が含まれます。
サービスのテストを示すために、サンプル アプリで次のサービスを確認します。
サンプル コードを表示またはダウンロードします (ダウンロード方法)。
TesterService
は、gRPC の 4 つのメソッドの型を使用して応答を返します。
public class TesterService : Tester.TesterBase
{
private readonly IGreeter _greeter;
public TesterService(IGreeter greeter)
{
_greeter = greeter;
}
public override Task<HelloReply> SayHelloUnary(HelloRequest request,
ServerCallContext context)
{
var message = _greeter.Greet(request.Name);
return Task.FromResult(new HelloReply { Message = message });
}
public override async Task SayHelloServerStreaming(HelloRequest request,
IServerStreamWriter<HelloReply> responseStream, ServerCallContext context)
{
var i = 0;
while (!context.CancellationToken.IsCancellationRequested)
{
var message = _greeter.Greet($"{request.Name} {++i}");
await responseStream.WriteAsync(new HelloReply { Message = message });
await Task.Delay(1000);
}
}
public override async Task<HelloReply> SayHelloClientStreaming(
IAsyncStreamReader<HelloRequest> requestStream, ServerCallContext context)
{
var names = new List<string>();
await foreach (var request in requestStream.ReadAllAsync())
{
names.Add(request.Name);
}
var message = _greeter.Greet(string.Join(", ", names));
return new HelloReply { Message = message };
}
public override async Task SayHelloBidirectionalStreaming(
IAsyncStreamReader<HelloRequest> requestStream,
IServerStreamWriter<HelloReply> responseStream,
ServerCallContext context)
{
await foreach (var request in requestStream.ReadAllAsync())
{
await responseStream.WriteAsync(
new HelloReply { Message = _greeter.Greet(request.Name) });
}
}
}
上記の gRPC サービス:
- 明示的な依存関係の原則に従います。
- 依存関係の注入 (DI) を予期して、
IGreeter
のインスタンスを提供します。 - モック オブジェクト フレームワークを使用するモックされた
IGreeter
サービスでテストできます (Moq サービスなど)。 モック オブジェクトは、テストで使用されるプロパティとメソッドの動作が事前定義されている加工オブジェクトです。 詳細については、「ASP.NET Core での統合テスト」を参照してください。
単体テスト ライブラリでは、メソッドを呼び出して gRPC サービスを直接テストできます。 単体テストでは、gRPC サービスを分離してテストします。
[Fact]
public async Task SayHelloUnaryTest()
{
// Arrange
var mockGreeter = new Mock<IGreeter>();
mockGreeter.Setup(
m => m.Greet(It.IsAny<string>())).Returns((string s) => $"Hello {s}");
var service = new TesterService(mockGreeter.Object);
// Act
var response = await service.SayHelloUnary(
new HelloRequest { Name = "Joe" }, TestServerCallContext.Create());
// Assert
mockGreeter.Verify(v => v.Greet("Joe"));
Assert.Equal("Hello Joe", response.Message);
}
上記の単体テスト:
- Moq を使用して
IGreeter
をモックします。 - 要求メッセージと
ServerCallContext
を使用してSayHelloUnary
メソッドを実行します。 すべてのサービス メソッドにServerCallContext
引数があります。 このテストでは、TestServerCallContext.Create()
ヘルパー メソッドを使用して型を指定します。 このヘルパー メソッドはサンプル コードに含まれています。 - アサーションを作成します。
- 要求名が
IGreeter
に渡されていることを確認します。 - サービスは、予期された応答メッセージを返します。
- 要求名が
gRPC メソッドは、ServerCallContext.GetHttpContext
拡張メソッドを使用して要求の HttpContext にアクセスできます。 HttpContext
を使用するメソッドを単体テストするには、テストの設定時にコンテキストを構成する必要があります。 HttpContext が構成されていない場合、GetHttpContext
で null
が返されます。
テストの設定時に HttpContext
を構成するには、新しいインスタンスを作成し、__HttpContext
キーを使用して ServerCallContext.UserState
コレクションに追加します。
var httpContext = new DefaultHttpContext();
var serverCallContext = TestServerCallContext.Create();
serverCallContext.UserState["__HttpContext"] = httpContext;
構成済みの HttpContext
インスタンスを使用するこの呼び出しコンテキストでサービス メソッドを実行します。
統合テストでは 単体テストよりも広範なレベルでアプリのコンポーネントを評価します。 gRPC アプリは、Microsoft.AspNetCore.TestHost
パッケージのメモリ内テスト サーバーである TestServer でホストされています。
単体テスト ライブラリによって gRPC アプリが起動され、gRPC クライアントを使用して gRPC サービスがテストされます。
サンプル コードには、統合テストを可能にするインフラストラクチャが含まれています。
GrpcTestFixture<TStartup>
クラスでは、ASP.NET Core ホストを構成し、メモリ内テスト サーバーで gRPC アプリを起動します。IntegrationTestBase
クラスは、統合テストの継承元である基本データ型です。 これには、フィクスチャの状態と、gRPC アプリを呼び出す gRPC クライアントを作成するための API が含まれています。
[Fact]
public async Task SayHelloUnaryTest()
{
// Arrange
var client = new Tester.TesterClient(Channel);
// Act
var response = await client.SayHelloUnaryAsync(new HelloRequest { Name = "Joe" });
// Assert
Assert.Equal("Hello Joe", response.Message);
}
上記の統合テスト:
IntegrationTestBase
によって提供されるチャネルを使用して、gRPC クライアントを作成します。 この型はサンプル コードに含まれています。- gRPC クライアントを使用して
SayHelloUnary
メソッドを呼び出します。 - サービスから予期された応答メッセージが返されることをアサートします。
フィクスチャで ConfigureWebHost
を使用して依存関係をオーバーライドします。 依存関係のオーバーライドは、テスト環境で外部依存関係が使用できない場合に役立ちます。 たとえば、外部支払いゲートウェイを使用するアプリは、テストの実行時にその外部依存関係を呼び出すことはできません。 代わりに、テストにモック ゲートウェイを使用します。
public MockedGreeterServiceTests(GrpcTestFixture<Startup> fixture,
ITestOutputHelper outputHelper) : base(fixture, outputHelper)
{
var mockGreeter = new Mock<IGreeter>();
mockGreeter.Setup(
m => m.Greet(It.IsAny<string>())).Returns((string s) =>
{
if (string.IsNullOrEmpty(s))
{
throw new ArgumentException("Name not provided.");
}
return $"Test {s}";
});
Fixture.ConfigureWebHost(builder =>
{
builder.ConfigureServices(
services => services.AddSingleton(mockGreeter.Object));
});
}
[Fact]
public async Task SayHelloUnaryTest_MockGreeter_Success()
{
// Arrange
var client = new Tester.TesterClient(Channel);
// Act
var response = await client.SayHelloUnaryAsync(
new HelloRequest { Name = "Joe" });
// Assert
Assert.Equal("Test Joe", response.Message);
}
上記の統合テスト:
- テスト クラス (
MockedGreeterServiceTests
) のコンストラクター:- Moq を使用して
IGreeter
をモックします。 ConfigureWebHost
を使用して、依存関係挿入に登録されたIGreeter
をオーバーライドします。
- Moq を使用して
- gRPC クライアントを使用して
SayHelloUnary
メソッドを呼び出します。 - モック
IGreeter
インスタンスに基づいて、予期される応答メッセージをアサートします。
ASP.NET Core に関するフィードバック
ASP.NET Core はオープンソース プロジェクトです。 フィードバックを提供するにはリンクを選択します。