Skip to content

Commit a827783

Browse files
committed
Use PactVerifier for grpc greeter tests
1 parent 00c6155 commit a827783

File tree

10 files changed

+228
-171
lines changed

10 files changed

+228
-171
lines changed

samples/Grpc/GrpcGreeter.Tests/GrpcGreeter.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
</ItemGroup>
1515
<ItemGroup>
1616
<ProjectReference Include="..\..\..\src\PactNet.Interop\PactNet.Interop.csproj" />
17+
<ProjectReference Include="..\..\..\src\PactNet.Output.Xunit\PactNet.Output.Xunit.csproj" />
18+
<ProjectReference Include="..\..\..\src\PactNet\PactNet.csproj" />
1719
<ProjectReference Include="..\GrpcGreeter\GrpcGreeter.csproj" />
1820
</ItemGroup>
1921
<ItemGroup>
Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,50 @@
1-
using System.Threading.Tasks;
2-
using System.Threading;
3-
using FluentAssertions;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
44
using PactNet;
5+
using PactNet.Exceptions;
6+
using PactNet.Infrastructure.Outputters;
57
using Xunit;
6-
using PactNet.Interop;
8+
using PactNet.Output.Xunit;
9+
using PactNet.Verifier;
10+
using Xunit.Abstractions;
711

812
namespace GrpcGreeter.Tests
913
{
10-
public class GrpcGreeterTests
14+
public class GrpcGreeterTests(ITestOutputHelper output, ServerFixture serverFixture) : IClassFixture<ServerFixture>, IDisposable
1115
{
12-
public GrpcGreeterTests()
16+
private readonly PactVerifier verifier = new("Grpc Greeter Api", new PactVerifierConfig
1317
{
14-
PactLogLevel.Information.InitialiseLogging();
15-
}
18+
LogLevel = PactLogLevel.Debug,
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");
1627

1728
[Fact]
18-
public void ReturnsVerificationFailureWhenNoRunningProvider()
29+
public void VerificationThrowsExceptionWhenNoRunningProvider()
1930
{
20-
var verifier = NativeInterop.VerifierNewForApplication("pact-dotnet","0.0.0");
21-
NativeInterop.VerifierSetProviderInfo(verifier,"grpc-greeter",null,null,0,null);
22-
NativeInterop.AddProviderTransport(verifier, "grpc",5060,"/","http");
23-
NativeInterop.VerifierAddFileSource(verifier,"../../../../pacts/grpc-greeter-client-grpc-greeter.json");
24-
var VerifierExecuteResult = NativeInterop.VerifierExecute(verifier);
25-
VerifierExecuteResult.Should().Be(1);
31+
Assert.Throws<PactVerificationFailedException>(() => verifier
32+
.WithEndpoint("grpc", new Uri("http://localhost:5060"))
33+
.WithFileSource(new FileInfo(pactPath))
34+
.Verify());
2635
}
36+
2737
[Fact]
28-
public async Task ReturnsVerificationSuccessRunningProviderAsync()
38+
public void VerificationSuccessForRunningProvider()
2939
{
30-
var verifier = NativeInterop.VerifierNewForApplication("pact-dotnet", "0.0.0");
31-
NativeInterop.VerifierSetProviderInfo(verifier, "grpc-greeter", null, null, 0, null);
32-
NativeInterop.AddProviderTransport(verifier, "grpc", 5000, "/", "https");
33-
NativeInterop.VerifierAddFileSource(verifier, "../../../../pacts/grpc-greeter-client-grpc-greeter.json");
34-
35-
// Arrange
36-
// Setup our app to run before our verifier executes
37-
// Setup a cancellation token so we can shutdown the app after
38-
var cts = new CancellationTokenSource();
39-
var token = cts.Token;
40-
var runAppTask = Task.Run(async () =>
41-
{
42-
await GrpcGreeterService.RunApp([], token);
43-
}, token);
44-
await Task.Delay(2000);
40+
verifier.WithEndpoint("grpc", serverFixture.ProviderUri)
41+
.WithFileSource(new FileInfo(pactPath))
42+
.Verify();
43+
}
4544

46-
// Act
47-
var VerifierExecuteResult = NativeInterop.VerifierExecute(verifier);
48-
VerifierExecuteResult.Should().Be(0);
49-
NativeInterop.VerifierShutdown(verifier);
50-
// After test execution, signal the task to terminate
51-
cts.Cancel();
45+
public void Dispose()
46+
{
47+
this.verifier?.Dispose();
5248
}
5349
}
5450
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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+
PactLogLevel.Information.InitialiseLogging();
17+
this.server = Host.CreateDefaultBuilder()
18+
.ConfigureWebHostDefaults(webBuilder =>
19+
{
20+
webBuilder.UseUrls(this.ProviderUri.ToString());
21+
webBuilder.UseStartup<Startup>();
22+
})
23+
.Build();
24+
25+
this.server.Start();
26+
}
27+
28+
public void Dispose() => this.server?.Dispose();
29+
}
Lines changed: 8 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,16 @@
1-
using GrpcGreeter.Services;
1+
namespace GrpcGreeter;
22

33
public class GrpcGreeterService
44
{
5-
public static async Task Main(string[] args)
5+
public static void Main(string[] args)
66
{
7-
await RunApp(args, CancellationToken.None);
7+
CreateHostBuilder(args).Build().Run();
88
}
99

10-
public static async Task RunApp(string[] args, CancellationToken cancellationToken)
11-
{
12-
var builder = WebApplication.CreateBuilder(args);
13-
14-
// Add services to the container.
15-
builder.Services.AddGrpc();
16-
builder.Services.AddGrpcReflection();
17-
18-
19-
var app = builder.Build();
20-
21-
// Configure the HTTP request pipeline.
22-
app.MapGrpcService<GreeterService>();
23-
app.MapGet("/", () => "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");
24-
app.MapGrpcReflectionService();
25-
26-
var cancellationTokenSource = new CancellationTokenSource();
27-
var periodicCancellationTask = PeriodicallyCheckCancellation(cancellationToken, cancellationTokenSource);
28-
29-
await app.RunAsync();
30-
31-
cancellationTokenSource.Cancel();
32-
await periodicCancellationTask;
33-
}
34-
35-
private static async Task PeriodicallyCheckCancellation(CancellationToken cancellationToken, CancellationTokenSource periodicCancellationToken)
36-
{
37-
while (!cancellationToken.IsCancellationRequested)
38-
{
39-
if (periodicCancellationToken.Token.IsCancellationRequested)
10+
public static IHostBuilder CreateHostBuilder(string[] args) =>
11+
Host.CreateDefaultBuilder(args)
12+
.ConfigureWebHostDefaults(webBuilder =>
4013
{
41-
periodicCancellationToken.Cancel();
42-
break;
43-
}
44-
45-
await Task.Delay(1000); // Check for cancellation every second
46-
}
47-
}
14+
webBuilder.UseStartup<Startup>();
15+
});
4816
}
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+
}

src/PactNet.Abstractions/Verifier/IPactVerifier.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ namespace PactNet.Verifier
1010
/// </summary>
1111
public interface IPactVerifier
1212
{
13+
/// <summary>
14+
/// Add an endpoint with a given protocol for verifying pacts containing synchronous interactions
15+
/// </summary>
16+
/// <param name="protocol"></param>
17+
/// <param name="pactUri"></param>
18+
/// <returns>Fluent builder</returns>
19+
IPactVerifier WithEndpoint(string protocol, Uri pactUri);
20+
1321
/// <summary>
1422
/// Add a HTTP endpoint for verifying pacts containing synchronous HTTP interactions
1523
/// </summary>

src/PactNet.Interop/NativeInterop.cs

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -77,81 +77,5 @@ public static class NativeInterop
7777
public static extern IntPtr MessageReify(InteractionHandle message);
7878

7979
#endregion Http Interop Support
80-
81-
#region Verifier Support
82-
83-
[DllImport(DllName, EntryPoint = "pactffi_verifier_new_for_application")]
84-
public static extern IntPtr VerifierNewForApplication(string name, string version);
85-
86-
[DllImport(DllName, EntryPoint = "pactffi_verifier_shutdown")]
87-
public static extern IntPtr VerifierShutdown(IntPtr handle);
88-
89-
[DllImport(DllName, EntryPoint = "pactffi_verifier_set_provider_info")]
90-
public static extern void VerifierSetProviderInfo(IntPtr handle, string name, string scheme, string host, ushort port, string path);
91-
92-
[DllImport(DllName, EntryPoint = "pactffi_verifier_add_provider_transport")]
93-
public static extern void AddProviderTransport(IntPtr handle, string protocol, ushort port, string path, string scheme);
94-
95-
[DllImport(DllName, EntryPoint = "pactffi_verifier_set_filter_info")]
96-
public static extern void VerifierSetFilterInfo(IntPtr handle, string description, string state, byte noState);
97-
98-
[DllImport(DllName, EntryPoint = "pactffi_verifier_set_provider_state")]
99-
public static extern void VerifierSetProviderState(IntPtr handle, string url, byte teardown, byte body);
100-
101-
[DllImport(DllName, EntryPoint = "pactffi_verifier_set_verification_options")]
102-
public static extern void VerifierSetVerificationOptions(IntPtr handle,
103-
byte disableSslVerification,
104-
uint requestTimeout);
105-
106-
[DllImport(DllName, EntryPoint = "pactffi_verifier_set_publish_options")]
107-
public static extern void VerifierSetPublishOptions(IntPtr handle,
108-
string providerVersion,
109-
string buildUrl,
110-
string[] providerTags,
111-
ushort providerTagsLength,
112-
string providerBranch);
113-
114-
[DllImport(DllName, EntryPoint = "pactffi_verifier_set_consumer_filters")]
115-
public static extern void VerifierSetConsumerFilters(IntPtr handle, string[] consumerFilters, ushort consumerFiltersLength);
116-
117-
[DllImport(DllName, EntryPoint = "pactffi_verifier_add_custom_header")]
118-
public static extern void AddCustomHeader(IntPtr handle, string name, string value);
119-
120-
[DllImport(DllName, EntryPoint = "pactffi_verifier_add_file_source")]
121-
public static extern void VerifierAddFileSource(IntPtr handle, string file);
122-
123-
[DllImport(DllName, EntryPoint = "pactffi_verifier_add_directory_source")]
124-
public static extern void VerifierAddDirectorySource(IntPtr handle, string directory);
125-
126-
[DllImport(DllName, EntryPoint = "pactffi_verifier_url_source")]
127-
public static extern void VerifierUrlSource(IntPtr handle, string url, string username, string password, string token);
128-
129-
[DllImport(DllName, EntryPoint = "pactffi_verifier_broker_source_with_selectors")]
130-
public static extern void VerifierBrokerSourceWithSelectors(IntPtr handle,
131-
string url,
132-
string username,
133-
string password,
134-
string token,
135-
byte enablePending,
136-
string includeWipPactsSince,
137-
string[] providerTags,
138-
ushort providerTagsLength,
139-
string providerBranch,
140-
string[] consumerVersionSelectors,
141-
ushort consumerVersionSelectorsLength,
142-
string[] consumerVersionTags,
143-
ushort consumerVersionTagsLength);
144-
145-
[DllImport(DllName, EntryPoint = "pactffi_verifier_execute")]
146-
public static extern int VerifierExecute(IntPtr handle);
147-
148-
[DllImport(DllName, EntryPoint = "pactffi_verifier_logs")]
149-
public static extern IntPtr VerifierLogs(IntPtr handle);
150-
151-
152-
[DllImport(DllName, EntryPoint = "pactffi_verifier_output")]
153-
public static extern IntPtr VerifierOutput(IntPtr handle, byte stripAnsi);
154-
155-
#endregion
15680
}
15781
}

0 commit comments

Comments
 (0)