Skip to content

feat: Add Aspire AppHost testing.#1

Open
newmancodes wants to merge 8 commits into
mainfrom
feature/add-aspire-apphost-testing
Open

feat: Add Aspire AppHost testing.#1
newmancodes wants to merge 8 commits into
mainfrom
feature/add-aspire-apphost-testing

Conversation

@newmancodes

Copy link
Copy Markdown
Owner

No description provided.

Copilot AI review requested due to automatic review settings April 12, 2026 09:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds initial infrastructure to run Aspire AppHost-related tests and wires them into CI for PR validation.

Changes:

  • Adds a new DistHaul.Tests xUnit project configured for Microsoft.Testing.Platform.
  • Updates the Aspire AppHost project and Aspire config to align with the new DistHaul.AppHost location/name.
  • Extends the GitHub Actions workflow to run .NET restore/build/test as part of the end-to-end job (including on pull requests).

Reviewed changes

Copilot reviewed 8 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
global.json Configures dotnet test runner selection (Microsoft.Testing.Platform).
DistHaul/DistHaul.Tests/xunit.runner.json Adds xUnit runner schema file for the new test project.
DistHaul/DistHaul.Tests/UnitTest1.cs Adds a placeholder test class/test.
DistHaul/DistHaul.Tests/DistHaul.Tests.csproj Introduces a new test project referencing the AppHost and MTP-enabled xUnit packages.
DistHaul/DistHaul.sln Adds the new test project and renames/relocates the AppHost entry.
DistHaul/DistHaul.AppHost/Properties/launchSettings.json Adds launch profiles for the AppHost.
DistHaul/DistHaul.AppHost/Program.cs Introduces the Aspire distributed application composition (Keycloak/Kafka/Redis/Postgres + executables).
DistHaul/DistHaul.AppHost/DistHaul.AppHost.csproj Enables warnings-as-errors and adds Aspire.Hosting.Testing.
DistHaul/.gitignore Adds a standard .NET-focused gitignore for the DistHaul/ subtree.
aspire.config.json Updates the configured AppHost path to DistHaul/DistHaul.AppHost.
.github/workflows/main.yml Runs the new AppHost restore/build/test steps and triggers on PRs to main.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .github/workflows/main.yml Outdated
working-directory: DistHaul

- name: Build Aspire AppHost
run: dotnet build DistHaul.sln --confiugration Release --no-restore

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dotnet build command has a misspelled option (--confiugration), which will cause this step to fail. Use the correct --configuration option name.

Suggested change
run: dotnet build DistHaul.sln --confiugration Release --no-restore
run: dotnet build DistHaul.sln --configuration Release --no-restore

Copilot uses AI. Check for mistakes.
Comment thread .github/workflows/main.yml Outdated
working-directory: DistHaul

- name: Build Aspire AppHost
run: dotnet build DistHaul.sln --confiugration Release --no-restore

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This dotnet build DistHaul.sln step runs from the repo root (no working-directory), but DistHaul.sln appears to live under the DistHaul/ folder (as used in the restore step). Either set working-directory: DistHaul here or update the command to build DistHaul/DistHaul.sln.

Suggested change
run: dotnet build DistHaul.sln --confiugration Release --no-restore
run: dotnet build DistHaul.sln --confiugration Release --no-restore
working-directory: DistHaul

Copilot uses AI. Check for mistakes.
Comment thread .github/workflows/main.yml Outdated
run: dotnet build DistHaul.sln --confiugration Release --no-restore

- name: Execute Aspire AppHost Tests
run: dotnet test --solution .\DistHaul.sln --configuration Release --no-build --verbosity normal --results-directory .\TestResults --coverage --coverage-output-format cobertura

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dotnet test doesn’t support a --solution option; the solution or project should be passed as a positional argument (e.g., dotnet test DistHaul.sln). As written, this will fail argument parsing.

Suggested change
run: dotnet test --solution .\DistHaul.sln --configuration Release --no-build --verbosity normal --results-directory .\TestResults --coverage --coverage-output-format cobertura
run: dotnet test DistHaul.sln --configuration Release --no-build --verbosity normal --results-directory ./TestResults --coverage --coverage-output-format cobertura

Copilot uses AI. Check for mistakes.
Comment thread .github/workflows/main.yml Outdated
run: dotnet build DistHaul.sln --confiugration Release --no-restore

- name: Execute Aspire AppHost Tests
run: dotnet test --solution .\DistHaul.sln --configuration Release --no-build --verbosity normal --results-directory .\TestResults --coverage --coverage-output-format cobertura

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This job uses shell: bash but passes Windows-style paths (.\DistHaul.sln, .\TestResults). In bash, backslashes will be treated as escapes and likely resolve to the wrong paths (or not resolve at all). Use ./DistHaul.sln and ./TestResults (or just DistHaul.sln / TestResults) to be portable on ubuntu-latest.

Suggested change
run: dotnet test --solution .\DistHaul.sln --configuration Release --no-build --verbosity normal --results-directory .\TestResults --coverage --coverage-output-format cobertura
run: dotnet test --solution ./DistHaul.sln --configuration Release --no-build --verbosity normal --results-directory ./TestResults --coverage --coverage-output-format cobertura

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +9
namespace DistHaul.Tests;

public class UnitTest1
{
[Fact]
public void Test1()
{
Assert.True(true);
}

Copilot AI Apr 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assert.True(true) is a no-op test and won’t catch regressions. Replace this with a meaningful test that exercises the Aspire AppHost (e.g., using Aspire.Hosting.Testing to start the distributed app and assert expected resources/endpoints are healthy).

Suggested change
namespace DistHaul.Tests;
public class UnitTest1
{
[Fact]
public void Test1()
{
Assert.True(true);
}
using System.Reflection;
using Aspire.Hosting.Testing;
namespace DistHaul.Tests;
public class UnitTest1
{
[Fact]
public async Task Test1()
{
var appHostType = FindAppHostType();
Assert.NotNull(appHostType);
var builder = await CreateTestingBuilderAsync(appHostType!);
Assert.NotNull(builder);
var buildAsyncMethod = builder.GetType().GetMethod("BuildAsync", Type.EmptyTypes);
Assert.NotNull(buildAsyncMethod);
var buildTask = (Task)buildAsyncMethod!.Invoke(builder, null)!;
await buildTask;
var app = buildTask.GetType().GetProperty("Result")!.GetValue(buildTask);
Assert.NotNull(app);
try
{
var startAsyncMethod = app!.GetType().GetMethod("StartAsync", Type.EmptyTypes);
Assert.NotNull(startAsyncMethod);
var startTask = (Task)startAsyncMethod!.Invoke(app, null)!;
await startTask;
}
finally
{
if (app is IAsyncDisposable asyncDisposable)
{
await asyncDisposable.DisposeAsync();
}
else if (app is IDisposable disposable)
{
disposable.Dispose();
}
}
}
private static Type? FindAppHostType()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
Type? appHostType;
try
{
appHostType = assembly
.GetTypes()
.FirstOrDefault(t =>
t is { IsClass: true, IsAbstract: false } &&
t.Namespace == "Projects" &&
t.Name.EndsWith("_AppHost", StringComparison.Ordinal));
}
catch (ReflectionTypeLoadException ex)
{
appHostType = ex.Types.FirstOrDefault(t =>
t is { IsClass: true, IsAbstract: false } &&
t.Namespace == "Projects" &&
t.Name.EndsWith("_AppHost", StringComparison.Ordinal));
}
if (appHostType is not null)
{
return appHostType;
}
}
return null;
}
private static async Task<object> CreateTestingBuilderAsync(Type appHostType)
{
var createAsyncMethod = typeof(DistributedApplicationTestingBuilder)
.GetMethods(BindingFlags.Public | BindingFlags.Static)
.First(m => m.Name == "CreateAsync" && m.IsGenericMethodDefinition && m.GetParameters().Length == 0)
.MakeGenericMethod(appHostType);
var createTask = (Task)createAsyncMethod.Invoke(null, null)!;
await createTask;
return createTask.GetType().GetProperty("Result")!.GetValue(createTask)!;
}

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants