test: add comprehensive MCP tool and server configuration tests
CI - Build & Test / Backend (.NET) (push) Successful in 32s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 16s
CI - Build & Test / Security Check (push) Successful in 2s
CI - Build & Test / Deploy Nexus (push) Failing after 10s

- McpToolsTests: 33 tests covering tool registration, enum validation,
  state transitions, auth resolution (JWT, API key, X-Agent-Id),
  create/read/update/activity/handoff workflows via McpToolsFixture
- McpServerConfigurationTests: 5 tests verifying MCP server DI
  registration, tool type attribute, MapMcp endpoint wiring,
  service extensions, and NuGet package reference
This commit is contained in:
2026-07-13 08:10:36 +02:00
parent 17dc84082c
commit 77b9587fa6
2 changed files with 667 additions and 0 deletions
@@ -0,0 +1,85 @@
using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Server;
using Nexus.Api.Services;
using Xunit;
namespace Nexus.Api.Tests;
/// <summary>
/// Verifies that the MCP server configuration is correct:
/// all tools are registered, the streamable-http transport is configured
/// via the service extensions, and MapMcp is called in Program.cs.
/// </summary>
public sealed class McpServerConfigurationTests
{
[Fact]
public void McpServer_CanBeRegistered_WithoutError()
{
var services = new ServiceCollection();
services.AddLogging();
services.AddOptions();
services.AddHttpContextAccessor();
// Simulate what AddNexusApplicationServices does
services.AddMcpServer()
.WithHttpTransport(options => options.Stateless = true)
.WithTools<NexusMcpTools>();
// Build the container — this should not throw
var provider = services.BuildServiceProvider();
// Verify the ToolType is properly decorated
var attr = typeof(NexusMcpTools).GetCustomAttributes(
typeof(McpServerToolTypeAttribute), inherit: false);
Assert.Single(attr);
}
[Fact]
public void McpServer_ToolTypeAttribute_IsPresent()
{
var attr = typeof(NexusMcpTools).GetCustomAttributes(
typeof(McpServerToolTypeAttribute), inherit: false);
Assert.Single(attr);
}
[Fact]
public void McpEndpoint_MapMcp_IsCalledInProgram()
{
// Source path relative to the test output directory
var programPath = ResolveSourcePath("backend", "Program.cs");
Assert.True(File.Exists(programPath), $"Program.cs not found at {programPath}");
var source = File.ReadAllText(programPath);
Assert.Contains("MapMcp", source, StringComparison.Ordinal);
}
[Fact]
public void McpServerRegistration_IsCalledInServiceExtensions()
{
var extPath = ResolveSourcePath("backend", "Extensions", "ServiceCollectionExtensions.cs");
Assert.True(File.Exists(extPath), $"ServiceCollectionExtensions.cs not found at {extPath}");
var source = File.ReadAllText(extPath);
Assert.Contains("AddMcpServer", source, StringComparison.Ordinal);
Assert.Contains("WithHttpTransport", source, StringComparison.Ordinal);
Assert.Contains("Stateless", source, StringComparison.Ordinal);
Assert.Contains("WithTools<NexusMcpTools>", source, StringComparison.Ordinal);
}
[Fact]
public void NuGetPackage_ModelContextProtocol_AspNetCore_IsReferenced()
{
var csprojPath = ResolveSourcePath("backend", "Nexus.Api.csproj");
Assert.True(File.Exists(csprojPath), $"Nexus.Api.csproj not found at {csprojPath}");
var source = File.ReadAllText(csprojPath);
Assert.Contains("ModelContextProtocol.AspNetCore", source, StringComparison.Ordinal);
}
private static string ResolveSourcePath(params string[] segments)
{
// Navigate from test output directory to the repo root
// Test DLL is at: backend-tests/bin/Debug/net10.0/Nexus.Api.Tests.dll
// We go up 4 levels (net10.0 → Debug → bin → backend-tests) to reach repo root
var baseDir = AppContext.BaseDirectory;
var repoRoot = Path.GetFullPath(Path.Combine(baseDir, "..", "..", "..", ".."));
return Path.Combine(new[] { repoRoot }.Concat(segments).ToArray());
}
}