Skip to content

Commit 63d1758

Browse files
committed
test(grpc): Add Grpc Sample
1 parent 51d399e commit 63d1758

File tree

19 files changed

+619
-2
lines changed

19 files changed

+619
-2
lines changed

PactNet.sln

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
3737
EndProject
3838
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PactNet.Output.Xunit", "src\PactNet.Output.Xunit\PactNet.Output.Xunit.csproj", "{02E265A1-A7A2-4106-8F6A-5027FDC3FC50}"
3939
EndProject
40+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Grpc", "Grpc", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
41+
EndProject
42+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcGreeter", "samples\Grpc\GrpcGreeter\GrpcGreeter.csproj", "{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}"
43+
EndProject
44+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcGreeterClient", "samples\Grpc\GrpcGreeterClient\GrpcGreeterClient.csproj", "{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}"
45+
EndProject
46+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcGreeterClient.Tests", "samples\Grpc\GrpcGreeterClient.Tests\GrpcGreeterClient.Tests.csproj", "{13756BC3-0750-E2AF-E1F0-565855A3E636}"
47+
EndProject
48+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GrpcGreeter.Tests", "samples\Grpc\GrpcGreeter.Tests\GrpcGreeter.Tests.csproj", "{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}"
49+
EndProject
4050
Global
4151
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4252
Debug|Any CPU = Debug|Any CPU
@@ -155,6 +165,54 @@ Global
155165
{02E265A1-A7A2-4106-8F6A-5027FDC3FC50}.Release|x64.Build.0 = Release|Any CPU
156166
{02E265A1-A7A2-4106-8F6A-5027FDC3FC50}.Release|x86.ActiveCfg = Release|Any CPU
157167
{02E265A1-A7A2-4106-8F6A-5027FDC3FC50}.Release|x86.Build.0 = Release|Any CPU
168+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
169+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Debug|Any CPU.Build.0 = Debug|Any CPU
170+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Debug|x64.ActiveCfg = Debug|Any CPU
171+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Debug|x64.Build.0 = Debug|Any CPU
172+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Debug|x86.ActiveCfg = Debug|Any CPU
173+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Debug|x86.Build.0 = Debug|Any CPU
174+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Release|Any CPU.ActiveCfg = Release|Any CPU
175+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Release|Any CPU.Build.0 = Release|Any CPU
176+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Release|x64.ActiveCfg = Release|Any CPU
177+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Release|x64.Build.0 = Release|Any CPU
178+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Release|x86.ActiveCfg = Release|Any CPU
179+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69}.Release|x86.Build.0 = Release|Any CPU
180+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
181+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
182+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Debug|x64.ActiveCfg = Debug|Any CPU
183+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Debug|x64.Build.0 = Debug|Any CPU
184+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Debug|x86.ActiveCfg = Debug|Any CPU
185+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Debug|x86.Build.0 = Debug|Any CPU
186+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
187+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Release|Any CPU.Build.0 = Release|Any CPU
188+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Release|x64.ActiveCfg = Release|Any CPU
189+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Release|x64.Build.0 = Release|Any CPU
190+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Release|x86.ActiveCfg = Release|Any CPU
191+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A}.Release|x86.Build.0 = Release|Any CPU
192+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
193+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Debug|Any CPU.Build.0 = Debug|Any CPU
194+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Debug|x64.ActiveCfg = Debug|Any CPU
195+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Debug|x64.Build.0 = Debug|Any CPU
196+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Debug|x86.ActiveCfg = Debug|Any CPU
197+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Debug|x86.Build.0 = Debug|Any CPU
198+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Release|Any CPU.ActiveCfg = Release|Any CPU
199+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Release|Any CPU.Build.0 = Release|Any CPU
200+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Release|x64.ActiveCfg = Release|Any CPU
201+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Release|x64.Build.0 = Release|Any CPU
202+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Release|x86.ActiveCfg = Release|Any CPU
203+
{13756BC3-0750-E2AF-E1F0-565855A3E636}.Release|x86.Build.0 = Release|Any CPU
204+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
205+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
206+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Debug|x64.ActiveCfg = Debug|Any CPU
207+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Debug|x64.Build.0 = Debug|Any CPU
208+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Debug|x86.ActiveCfg = Debug|Any CPU
209+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Debug|x86.Build.0 = Debug|Any CPU
210+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
211+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Release|Any CPU.Build.0 = Release|Any CPU
212+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Release|x64.ActiveCfg = Release|Any CPU
213+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Release|x64.Build.0 = Release|Any CPU
214+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Release|x86.ActiveCfg = Release|Any CPU
215+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6}.Release|x86.Build.0 = Release|Any CPU
158216
EndGlobalSection
159217
GlobalSection(SolutionProperties) = preSolution
160218
HideSolutionNode = FALSE
@@ -170,6 +228,11 @@ Global
170228
{5E915D66-917B-4730-B31A-C9727C196346} = {6663C12E-9912-40D0-9310-D119D1F6B023}
171229
{D8B75E48-6E45-468B-8049-B73823C14CB8} = {6663C12E-9912-40D0-9310-D119D1F6B023}
172230
{02E265A1-A7A2-4106-8F6A-5027FDC3FC50} = {CF67D7A1-AE96-420B-9971-65E535B903E8}
231+
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {547DB478-460A-428F-9371-1D653CE85DB5}
232+
{529F37CB-CDA0-6553-EAC9-8DAC2195ED69} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
233+
{917DAC61-55B4-D721-B1ED-B0E352E4CF1A} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
234+
{13756BC3-0750-E2AF-E1F0-565855A3E636} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
235+
{DC5371A0-7DE2-4CC5-D0E1-1DF6CB567FA6} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
173236
EndGlobalSection
174237
GlobalSection(ExtensibilityGlobals) = postSolution
175238
SolutionGuid = {C2CBC30C-92D4-4E3A-A5B8-1E5D4E938DFC}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>net8.0</TargetFramework>
4+
<IsPackable>false</IsPackable>
5+
</PropertyGroup>
6+
<ItemGroup>
7+
<PackageReference Include="FluentAssertions" Version="6.12.0" />
8+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
9+
<PackageReference Include="xunit" Version="2.6.6" />
10+
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.6">
11+
<PrivateAssets>all</PrivateAssets>
12+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
13+
</PackageReference>
14+
</ItemGroup>
15+
<ItemGroup>
16+
<ProjectReference Include="..\..\..\src\PactNet.Output.Xunit\PactNet.Output.Xunit.csproj" />
17+
<ProjectReference Include="..\..\..\src\PactNet\PactNet.csproj" />
18+
<ProjectReference Include="..\GrpcGreeter\GrpcGreeter.csproj" />
19+
</ItemGroup>
20+
<ItemGroup>
21+
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
22+
</ItemGroup>
23+
</Project>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using PactNet;
5+
using PactNet.Exceptions;
6+
using PactNet.Infrastructure.Outputters;
7+
using Xunit;
8+
using PactNet.Output.Xunit;
9+
using PactNet.Verifier;
10+
using Xunit.Abstractions;
11+
12+
namespace GrpcGreeter.Tests
13+
{
14+
public class GrpcGreeterTests(ITestOutputHelper output, ServerFixture serverFixture) : IClassFixture<ServerFixture>, IDisposable
15+
{
16+
private readonly PactVerifier verifier = new("Grpc Greeter Api", new PactVerifierConfig
17+
{
18+
LogLevel = PactLogLevel.Information,
19+
Outputters = new List<IOutput>
20+
{
21+
new XunitOutput(output)
22+
}
23+
});
24+
25+
private readonly string pactPath = Path.Combine("..", "..", "..", "..", "..", "Grpc", "pacts",
26+
"grpc-greeter-client-grpc-greeter.json");
27+
28+
[Fact]
29+
public void VerificationThrowsExceptionWhenNoRunningProvider()
30+
{
31+
Assert.Throws<PactVerificationFailedException>(() => verifier
32+
.WithHttpEndpoint(new Uri("http://localhost:5060"))
33+
.WithFileSource(new FileInfo(pactPath))
34+
.Verify());
35+
}
36+
37+
[Fact]
38+
public void VerificationSuccessForRunningProvider()
39+
{
40+
verifier.WithHttpEndpoint(serverFixture.ProviderUri)
41+
.WithFileSource(new FileInfo(pactPath))
42+
.Verify();
43+
}
44+
45+
public void Dispose()
46+
{
47+
this.verifier?.Dispose();
48+
}
49+
}
50+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using Microsoft.AspNetCore.Hosting;
3+
using Microsoft.Extensions.Hosting;
4+
using PactNet;
5+
using PactNet.Interop;
6+
7+
namespace GrpcGreeter.Tests;
8+
9+
public class ServerFixture : IDisposable
10+
{
11+
public readonly Uri ProviderUri = new("http://localhost:5000");
12+
private readonly IHost server;
13+
14+
public ServerFixture()
15+
{
16+
this.server = Host.CreateDefaultBuilder()
17+
.ConfigureWebHostDefaults(webBuilder =>
18+
{
19+
webBuilder.UseUrls(this.ProviderUri.ToString());
20+
webBuilder.UseStartup<Startup>();
21+
})
22+
.Build();
23+
24+
this.server.Start();
25+
}
26+
27+
public void Dispose() => this.server?.Dispose();
28+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net8.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />
11+
</ItemGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="Grpc.AspNetCore" Version="2.71.0" />
15+
<PackageReference Include="Grpc.AspNetCore.Server.Reflection" Version="2.71.0" />
16+
</ItemGroup>
17+
18+
</Project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace GrpcGreeter;
2+
3+
public class GrpcGreeterService
4+
{
5+
public static void Main(string[] args)
6+
{
7+
CreateHostBuilder(args).Build().Run();
8+
}
9+
10+
public static IHostBuilder CreateHostBuilder(string[] args) =>
11+
Host.CreateDefaultBuilder(args)
12+
.ConfigureWebHostDefaults(webBuilder =>
13+
{
14+
webBuilder.UseStartup<Startup>();
15+
});
16+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"$schema": "http://json.schemastore.org/launchsettings.json",
3+
"profiles": {
4+
"http": {
5+
"commandName": "Project",
6+
"dotnetRunMessages": true,
7+
"launchBrowser": false,
8+
"applicationUrl": "http://localhost:5251",
9+
"environmentVariables": {
10+
"ASPNETCORE_ENVIRONMENT": "Development"
11+
}
12+
},
13+
"https": {
14+
"commandName": "Project",
15+
"dotnetRunMessages": true,
16+
"launchBrowser": false,
17+
"applicationUrl": "https://localhost:7272;http://localhost:5251",
18+
"environmentVariables": {
19+
"ASPNETCORE_ENVIRONMENT": "Development"
20+
}
21+
}
22+
}
23+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
syntax = "proto3";
2+
3+
option csharp_namespace = "GrpcGreeter";
4+
5+
package greet;
6+
7+
// The greeting service definition.
8+
service Greeter {
9+
// Sends a greeting
10+
rpc SayHello (HelloRequest) returns (HelloReply);
11+
}
12+
13+
// The request message containing the user's name.
14+
message HelloRequest {
15+
string name = 1;
16+
}
17+
18+
// The response message containing the greetings.
19+
message HelloReply {
20+
string message = 1;
21+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Grpc.Core;
2+
using GrpcGreeter;
3+
4+
namespace GrpcGreeter.Services
5+
{
6+
public class GreeterService : Greeter.GreeterBase
7+
{
8+
private readonly ILogger<GreeterService> _logger;
9+
public GreeterService(ILogger<GreeterService> logger)
10+
{
11+
_logger = logger;
12+
}
13+
14+
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
15+
{
16+
return Task.FromResult(new HelloReply
17+
{
18+
Message = "Hello " + request.Name
19+
});
20+
}
21+
}
22+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using GrpcGreeter.Services;
2+
3+
namespace GrpcGreeter;
4+
5+
public class Startup
6+
{
7+
public IConfiguration Configuration { get; }
8+
9+
public Startup(IConfiguration configuration)
10+
{
11+
this.Configuration = configuration;
12+
}
13+
14+
// This method gets called by the runtime. Use this method to add services to the container.
15+
public void ConfigureServices(IServiceCollection services)
16+
{
17+
// Add services to the container.
18+
services.AddGrpc();
19+
services.AddGrpcReflection();
20+
21+
}
22+
23+
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
24+
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
25+
{
26+
app.UseRouting();
27+
app.UseEndpoints(b =>
28+
{
29+
// Configure the HTTP request pipeline.
30+
b.MapGrpcService<GreeterService>();
31+
b.MapGet("/",
32+
() =>
33+
"Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
34+
b.MapGrpcReflectionService();
35+
});
36+
}
37+
}

0 commit comments

Comments
 (0)