Skip to content

Commit 4e88e71

Browse files
test: use PublicApiGenerator with Verify for API approval
Co-authored-by: mauroservienti <1325611+mauroservienti@users.noreply.github.com>
1 parent 649859e commit 4e88e71

File tree

4 files changed

+37
-87
lines changed

4 files changed

+37
-87
lines changed

src/ServiceComposer.AspNetCore.Testing.Tests/PublicApi.approved.txt

Lines changed: 0 additions & 11 deletions
This file was deleted.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
[assembly: System.Reflection.AssemblyMetadata("RepositoryUrl", "https://github.com/ServiceComposer/ServiceComposer.AspNetCore.Testing")]
2+
[assembly: System.Runtime.Versioning.TargetFramework(".NETCoreApp,Version=v10.0", FrameworkDisplayName=".NET 10.0")]
3+
namespace ServiceComposer.AspNetCore.Testing
4+
{
5+
public class SelfContainedWebApplicationFactoryWithHost<TEntryPoint> : Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory<TEntryPoint>
6+
where TEntryPoint : class
7+
{
8+
public SelfContainedWebApplicationFactoryWithHost(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection> configureServices, System.Action<Microsoft.AspNetCore.Builder.IApplicationBuilder> configure, string[] args = null) { }
9+
public System.Action<Microsoft.Extensions.Hosting.IHostBuilder> HostBuilderCustomization { get; set; }
10+
public System.Action<Microsoft.AspNetCore.Hosting.IWebHostBuilder> WebHostBuilderCustomization { get; set; }
11+
protected override Microsoft.Extensions.Hosting.IHostBuilder CreateHostBuilder() { }
12+
}
13+
public class SelfContainedWebApplicationFactoryWithWebHost<TEntryPoint> : Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory<TEntryPoint>
14+
where TEntryPoint : class
15+
{
16+
public SelfContainedWebApplicationFactoryWithWebHost(System.Action<Microsoft.Extensions.DependencyInjection.IServiceCollection> configureServices, System.Action<Microsoft.AspNetCore.Builder.IApplicationBuilder> configure) { }
17+
public SelfContainedWebApplicationFactoryWithWebHost(System.Action<Microsoft.AspNetCore.Hosting.WebHostBuilderContext, Microsoft.Extensions.DependencyInjection.IServiceCollection> configureServices, System.Action<Microsoft.AspNetCore.Hosting.WebHostBuilderContext, Microsoft.AspNetCore.Builder.IApplicationBuilder> configure) { }
18+
public System.Action<Microsoft.AspNetCore.Hosting.IWebHostBuilder> BuilderCustomization { get; set; }
19+
protected override void ConfigureWebHost(Microsoft.AspNetCore.Hosting.IWebHostBuilder builder) { }
20+
protected override Microsoft.AspNetCore.Hosting.IWebHostBuilder CreateWebHostBuilder() { }
21+
}
22+
public class WebApplicationFactoryWithWebHost<TStartup> : Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory<TStartup>
23+
where TStartup : class
24+
{
25+
public WebApplicationFactoryWithWebHost() { }
26+
public System.Action<Microsoft.AspNetCore.Hosting.IWebHostBuilder> BuilderCustomization { get; set; }
27+
protected override void ConfigureWebHost(Microsoft.AspNetCore.Hosting.IWebHostBuilder builder) { }
28+
protected override Microsoft.AspNetCore.Hosting.IWebHostBuilder CreateWebHostBuilder() { }
29+
}
30+
}
Lines changed: 5 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,14 @@
1-
using System.Reflection;
2-
using System.Text;
1+
using PublicApiGenerator;
2+
using VerifyXunit;
33

44
namespace ServiceComposer.AspNetCore.Testing.Tests;
55

66
public class PublicApiApprovalTests
77
{
88
[Fact]
9-
public void Public_api_is_approved()
9+
public Task Public_api_is_approved()
1010
{
11-
var actual = GeneratePublicApi();
12-
var approvedPath = Path.Combine(AppContext.BaseDirectory, "PublicApi.approved.txt");
13-
var approved = File.ReadAllText(approvedPath);
14-
15-
Assert.Equal(Normalize(approved), Normalize(actual));
16-
}
17-
18-
static string GeneratePublicApi()
19-
{
20-
var assembly = typeof(WebApplicationFactoryWithWebHost<>).Assembly;
21-
var lines = new List<string>();
22-
23-
foreach (var type in assembly.GetExportedTypes().OrderBy(t => t.FullName, StringComparer.Ordinal))
24-
{
25-
lines.Add($"type {FormatTypeName(type)}");
26-
27-
foreach (var constructor in type.GetConstructors(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly).OrderBy(c => c.ToString(), StringComparer.Ordinal))
28-
{
29-
lines.Add($" ctor {FormatConstructor(constructor)}");
30-
}
31-
32-
foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly).OrderBy(p => p.Name, StringComparer.Ordinal))
33-
{
34-
lines.Add($" property {FormatTypeName(property.PropertyType)} {property.Name}");
35-
}
36-
37-
foreach (var method in type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly)
38-
.Where(m => !m.IsSpecialName)
39-
.OrderBy(m => m.ToString(), StringComparer.Ordinal))
40-
{
41-
lines.Add($" method {FormatTypeName(method.ReturnType)} {method.Name}({string.Join(", ", method.GetParameters().Select(FormatParameter))})");
42-
}
43-
}
44-
45-
return string.Join(Environment.NewLine, lines);
46-
}
47-
48-
static string FormatConstructor(ConstructorInfo constructor) => $"{constructor.DeclaringType!.Name}({string.Join(", ", constructor.GetParameters().Select(FormatParameter))})";
49-
50-
static string FormatParameter(ParameterInfo parameter) => $"{FormatTypeName(parameter.ParameterType)} {parameter.Name}";
51-
52-
static string FormatTypeName(Type type)
53-
{
54-
if (type.IsGenericType)
55-
{
56-
var genericTypeName = type.GetGenericTypeDefinition().FullName!;
57-
var tickIndex = genericTypeName.IndexOf('`');
58-
var typeName = tickIndex >= 0 ? genericTypeName[..tickIndex] : genericTypeName;
59-
return $"{typeName}<{string.Join(", ", type.GetGenericArguments().Select(FormatTypeName))}>";
60-
}
61-
62-
return type.FullName ?? type.Name;
63-
}
64-
65-
static string Normalize(string value)
66-
{
67-
var builder = new StringBuilder(value.Length);
68-
using var reader = new StringReader(value);
69-
string? line;
70-
var first = true;
71-
while ((line = reader.ReadLine()) != null)
72-
{
73-
if (!first)
74-
{
75-
builder.Append('\n');
76-
}
77-
78-
builder.Append(line.TrimEnd());
79-
first = false;
80-
}
81-
82-
return builder.ToString();
11+
var publicApi = ApiGenerator.GeneratePublicApi(typeof(WebApplicationFactoryWithWebHost<>).Assembly);
12+
return Verifier.Verify(publicApi);
8313
}
8414
}

src/ServiceComposer.AspNetCore.Testing.Tests/ServiceComposer.AspNetCore.Testing.Tests.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
<ItemGroup>
1111
<PackageReference Include="coverlet.collector" Version="6.0.4" />
1212
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
13+
<PackageReference Include="PublicApiGenerator" Version="11.5.4" />
14+
<PackageReference Include="Verify.Xunit" Version="31.12.5" />
1315
<PackageReference Include="xunit" Version="2.9.3" />
1416
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4" />
1517
</ItemGroup>
@@ -20,7 +22,6 @@
2022

2123
<ItemGroup>
2224
<ProjectReference Include="..\ServiceComposer.AspNetCore.Testing\ServiceComposer.AspNetCore.Testing.csproj" />
23-
<None Include="PublicApi.approved.txt" CopyToOutputDirectory="PreserveNewest" />
2425
</ItemGroup>
2526

2627
</Project>

0 commit comments

Comments
 (0)