diff --git a/Directory.Packages.props b/Directory.Packages.props index 9a1c43b..fa94ff2 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -50,11 +50,9 @@ - + + - - - diff --git a/src/MCPsharp/MCPsharp.csproj b/src/MCPsharp/MCPsharp.csproj index b8240b6..58dd5ed 100644 --- a/src/MCPsharp/MCPsharp.csproj +++ b/src/MCPsharp/MCPsharp.csproj @@ -2,7 +2,7 @@ Exe - net9.0 + net10.0 enable enable latest diff --git a/tests/MCPsharp.Tests/Integration/McpServerIntegrationTests.cs b/tests/MCPsharp.Tests/Integration/McpServerIntegrationTests.cs index 73b040e..3c1346e 100644 --- a/tests/MCPsharp.Tests/Integration/McpServerIntegrationTests.cs +++ b/tests/MCPsharp.Tests/Integration/McpServerIntegrationTests.cs @@ -1,21 +1,23 @@ using System.Text; using System.Text.Json; -using FluentAssertions; using MCPsharp.Services; using MCPsharp.Models; -using Xunit; +using NUnit.Framework; +using FileInfo = MCPsharp.Models.FileInfo; namespace MCPsharp.Tests.Integration; /// /// Integration tests that test the full MCP server workflow including JSON-RPC protocol compliance /// -public class McpServerIntegrationTests : IDisposable +[TestFixture] +public class McpServerIntegrationTests { - private readonly string _testProjectRoot; + private string _testProjectRoot = null!; private FileOperationsService _fileService = null!; - public McpServerIntegrationTests() + [SetUp] + public void SetUp() { // Create a temporary test project with sample C# files _testProjectRoot = Path.Combine(Path.GetTempPath(), $"mcpsharp-integration-test-{Guid.NewGuid()}"); @@ -23,7 +25,8 @@ public McpServerIntegrationTests() SetupTestProject(); } - public void Dispose() + [TearDown] + public void TearDown() { // Clean up test project if (Directory.Exists(_testProjectRoot)) @@ -99,7 +102,7 @@ public void Test_Helper() { } """); } - [Fact] + [Test] public void Test01_BasicProjectWorkflow_OpenAndListFiles() { // Arrange - Open project (simulated via direct service instantiation) @@ -109,14 +112,14 @@ public void Test01_BasicProjectWorkflow_OpenAndListFiles() var listResult = _fileService.ListFiles(); // Assert - listResult.Should().NotBeNull(); - listResult.TotalFiles.Should().BeGreaterThan(0); - listResult.Files.Should().Contain(f => f.RelativePath.Contains("Program.cs")); - listResult.Files.Should().Contain(f => f.RelativePath.Contains("Helper.cs")); - listResult.Files.Should().Contain(f => f.RelativePath.Contains("README.md")); + Assert.That(listResult, Is.Not.Null); + Assert.That(listResult.TotalFiles, Is.GreaterThan(0)); + Assert.That(listResult.Files, Has.Some.Matches(f => f.RelativePath.Contains("Program.cs"))); + Assert.That(listResult.Files, Has.Some.Matches(f => f.RelativePath.Contains("Helper.cs"))); + Assert.That(listResult.Files, Has.Some.Matches(f => f.RelativePath.Contains("README.md"))); } - [Fact] + [Test] public void Test02_BasicProjectWorkflow_ListCSharpFilesWithGlob() { // Arrange @@ -126,13 +129,13 @@ public void Test02_BasicProjectWorkflow_ListCSharpFilesWithGlob() var listResult = _fileService.ListFiles("**/*.cs"); // Assert - listResult.Should().NotBeNull(); - listResult.TotalFiles.Should().Be(3); // Program.cs, Helper.cs, ProgramTests.cs - listResult.Files.Should().OnlyContain(f => f.RelativePath.EndsWith(".cs")); - listResult.Pattern.Should().Be("**/*.cs"); + Assert.That(listResult, Is.Not.Null); + Assert.That(listResult.TotalFiles, Is.EqualTo(3)); // Program.cs, Helper.cs, ProgramTests.cs + Assert.That(listResult.Files, Has.All.Matches(f => f.RelativePath.EndsWith(".cs"))); + Assert.That(listResult.Pattern, Is.EqualTo("**/*.cs")); } - [Fact] + [Test] public async Task Test03_BasicProjectWorkflow_ReadFile() { // Arrange @@ -142,16 +145,16 @@ public async Task Test03_BasicProjectWorkflow_ReadFile() var readResult = await _fileService.ReadFileAsync("src/Program.cs"); // Assert - readResult.Should().NotBeNull(); - readResult.Success.Should().BeTrue(); - readResult.Content.Should().Contain("Hello, World!"); - readResult.Content.Should().Contain("namespace TestProject"); - readResult.LineCount.Should().BeGreaterThan(5); - readResult.Encoding.Should().Be("utf-8"); - readResult.Error.Should().BeNull(); + Assert.That(readResult, Is.Not.Null); + Assert.That(readResult.Success, Is.True); + Assert.That(readResult.Content, Does.Contain("Hello, World!")); + Assert.That(readResult.Content, Does.Contain("namespace TestProject")); + Assert.That(readResult.LineCount, Is.GreaterThan(5)); + Assert.That(readResult.Encoding, Is.EqualTo("utf-8")); + Assert.That(readResult.Error, Is.Null); } - [Fact] + [Test] public async Task Test04_FileEditingWorkflow_CreateAndReadFile() { // Arrange @@ -171,20 +174,20 @@ public class NewClass var writeResult = await _fileService.WriteFileAsync(newFileName, newContent); // Assert - Write succeeded - writeResult.Should().NotBeNull(); - writeResult.Success.Should().BeTrue(); - writeResult.Created.Should().BeTrue(); - writeResult.BytesWritten.Should().BeGreaterThan(0); + Assert.That(writeResult, Is.Not.Null); + Assert.That(writeResult.Success, Is.True); + Assert.That(writeResult.Created, Is.True); + Assert.That(writeResult.BytesWritten, Is.GreaterThan(0)); // Act - Read it back var readResult = await _fileService.ReadFileAsync(newFileName); // Assert - Content matches - readResult.Success.Should().BeTrue(); - readResult.Content.Should().Be(newContent); + Assert.That(readResult.Success, Is.True); + Assert.That(readResult.Content, Is.EqualTo(newContent)); } - [Fact] + [Test] public async Task Test05_FileEditingWorkflow_EditFile() { // Arrange @@ -193,7 +196,7 @@ public async Task Test05_FileEditingWorkflow_EditFile() // Read original content var originalContent = await _fileService.ReadFileAsync(fileName); - originalContent.Success.Should().BeTrue(); + Assert.That(originalContent.Success, Is.True); // Act - Edit the file (add a comment) var edits = new List @@ -211,19 +214,19 @@ public async Task Test05_FileEditingWorkflow_EditFile() var editResult = await _fileService.EditFileAsync(fileName, edits); // Assert - Edit succeeded - editResult.Success.Should().BeTrue(); - editResult.EditsApplied.Should().Be(1); - editResult.NewContent.Should().Contain("// This is a helper class"); + Assert.That(editResult.Success, Is.True); + Assert.That(editResult.EditsApplied, Is.EqualTo(1)); + Assert.That(editResult.NewContent, Does.Contain("// This is a helper class")); // Act - Read back to verify var readResult = await _fileService.ReadFileAsync(fileName); // Assert - Content was modified - readResult.Success.Should().BeTrue(); - readResult.Content.Should().Contain("// This is a helper class"); + Assert.That(readResult.Success, Is.True); + Assert.That(readResult.Content, Does.Contain("// This is a helper class")); } - [Fact] + [Test] public async Task Test06_MultipleOperations_SequentialReads() { // Arrange @@ -235,17 +238,17 @@ public async Task Test06_MultipleOperations_SequentialReads() var readmeResult = await _fileService.ReadFileAsync("README.md"); // Assert - All reads succeeded - programResult.Success.Should().BeTrue(); - programResult.Content.Should().Contain("Main"); + Assert.That(programResult.Success, Is.True); + Assert.That(programResult.Content, Does.Contain("Main")); - helperResult.Success.Should().BeTrue(); - helperResult.Content.Should().Contain("Helper"); + Assert.That(helperResult.Success, Is.True); + Assert.That(helperResult.Content, Does.Contain("Helper")); - readmeResult.Success.Should().BeTrue(); - readmeResult.Content.Should().Contain("Test Project"); + Assert.That(readmeResult.Success, Is.True); + Assert.That(readmeResult.Content, Does.Contain("Test Project")); } - [Fact] + [Test] public async Task Test07_ErrorHandling_ReadNonExistentFile() { // Arrange @@ -255,14 +258,14 @@ public async Task Test07_ErrorHandling_ReadNonExistentFile() var result = await _fileService.ReadFileAsync("src/DoesNotExist.cs"); // Assert - Proper error response - result.Should().NotBeNull(); - result.Success.Should().BeFalse(); - result.Error.Should().NotBeNullOrEmpty(); - result.Error.Should().Contain("not found"); - result.Content.Should().BeNull(); + Assert.That(result, Is.Not.Null); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null.And.Not.Empty); + Assert.That(result.Error, Does.Contain("not found")); + Assert.That(result.Content, Is.Null); } - [Fact] + [Test] public async Task Test08_ErrorHandling_ReadFileOutsideProject() { // Arrange @@ -272,25 +275,24 @@ public async Task Test08_ErrorHandling_ReadFileOutsideProject() var result = await _fileService.ReadFileAsync("../outside.cs"); // Assert - Security error - result.Should().NotBeNull(); - result.Success.Should().BeFalse(); - result.Error.Should().Contain("outside project root"); - result.Content.Should().BeNull(); + Assert.That(result, Is.Not.Null); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("outside project root")); + Assert.That(result.Content, Is.Null); } - [Fact] + [Test] public void Test09_ErrorHandling_OpenNonExistentProject() { // Arrange var nonExistentPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); // Act & Assert - Action act = () => new FileOperationsService(nonExistentPath); - act.Should().Throw() - .WithMessage($"Root path does not exist: {nonExistentPath}"); + var ex = Assert.Throws(() => new FileOperationsService(nonExistentPath)); + Assert.That(ex.Message, Is.EqualTo($"Root path does not exist: {nonExistentPath}")); } - [Fact] + [Test] public async Task Test10_ErrorHandling_WriteFileOutsideProject() { // Arrange @@ -300,12 +302,12 @@ public async Task Test10_ErrorHandling_WriteFileOutsideProject() var result = await _fileService.WriteFileAsync("../outside.cs", "content"); // Assert - Security error - result.Should().NotBeNull(); - result.Success.Should().BeFalse(); - result.Error.Should().Contain("outside project root"); + Assert.That(result, Is.Not.Null); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("outside project root")); } - [Fact] + [Test] public async Task Test11_CompleteWorkflow_CreateEditRead() { // Arrange @@ -315,8 +317,8 @@ public async Task Test11_CompleteWorkflow_CreateEditRead() // Act 1 - Create file var createResult = await _fileService.WriteFileAsync(fileName, initialContent); - createResult.Success.Should().BeTrue(); - createResult.Created.Should().BeTrue(); + Assert.That(createResult.Success, Is.True); + Assert.That(createResult.Created, Is.True); // Act 2 - Edit file (add method before closing brace) var edits = new List @@ -337,18 +339,18 @@ public async Task Test11_CompleteWorkflow_CreateEditRead() { throw new Exception($"Edit failed: {editResult.Error}"); } - editResult.Success.Should().BeTrue(); + Assert.That(editResult.Success, Is.True); // Act 3 - Read back final content var readResult = await _fileService.ReadFileAsync(fileName); // Assert - Verify complete workflow - readResult.Success.Should().BeTrue(); - readResult.Content.Should().Contain("public class Workflow"); - readResult.Content.Should().Contain("public void Execute()"); + Assert.That(readResult.Success, Is.True); + Assert.That(readResult.Content, Does.Contain("public class Workflow")); + Assert.That(readResult.Content, Does.Contain("public void Execute()")); } - [Fact] + [Test] public void Test12_GlobPatterns_CsprojFiles() { // Arrange @@ -358,11 +360,11 @@ public void Test12_GlobPatterns_CsprojFiles() var result = _fileService.ListFiles("**/*.csproj"); // Assert - result.TotalFiles.Should().Be(1); - result.Files.Should().ContainSingle(f => f.RelativePath.Contains("TestProject.csproj")); + Assert.That(result.TotalFiles, Is.EqualTo(1)); + Assert.That(result.Files, Has.Exactly(1).Matches(f => f.RelativePath.Contains("TestProject.csproj"))); } - [Fact] + [Test] public void Test13_GlobPatterns_TestFiles() { // Arrange @@ -372,11 +374,11 @@ public void Test13_GlobPatterns_TestFiles() var result = _fileService.ListFiles("tests/**/*.cs"); // Assert - result.TotalFiles.Should().Be(1); - result.Files.Should().ContainSingle(f => f.RelativePath.Contains("ProgramTests.cs")); + Assert.That(result.TotalFiles, Is.EqualTo(1)); + Assert.That(result.Files, Has.Exactly(1).Matches(f => f.RelativePath.Contains("ProgramTests.cs"))); } - [Fact] + [Test] public async Task Test14_ComplexEdits_MultipleEditsInOneFile() { // Arrange @@ -399,13 +401,13 @@ public async Task Test14_ComplexEdits_MultipleEditsInOneFile() var editResult = await _fileService.EditFileAsync(fileName, edits); // Assert - editResult.Success.Should().BeTrue(); - editResult.EditsApplied.Should().Be(3); - editResult.NewContent.Should().Contain("// Header"); - editResult.NewContent.Should().Contain("Modified Line 3"); + Assert.That(editResult.Success, Is.True); + Assert.That(editResult.EditsApplied, Is.EqualTo(3)); + Assert.That(editResult.NewContent, Does.Contain("// Header")); + Assert.That(editResult.NewContent, Does.Contain("Modified Line 3")); } - [Fact] + [Test] public async Task Test15_DirectoryCreation_NestedDirectories() { // Arrange @@ -417,17 +419,17 @@ public async Task Test15_DirectoryCreation_NestedDirectories() var result = await _fileService.WriteFileAsync(fileName, content, createDirectories: true); // Assert - result.Success.Should().BeTrue(); - result.Created.Should().BeTrue(); - File.Exists(Path.Combine(_testProjectRoot, fileName)).Should().BeTrue(); + Assert.That(result.Success, Is.True); + Assert.That(result.Created, Is.True); + Assert.That(File.Exists(Path.Combine(_testProjectRoot, fileName)), Is.True); // Verify can read it back var readResult = await _fileService.ReadFileAsync(fileName); - readResult.Success.Should().BeTrue(); - readResult.Content.Should().Be(content); + Assert.That(readResult.Success, Is.True); + Assert.That(readResult.Content, Is.EqualTo(content)); } - [Fact] + [Test] public void Test16_JsonSerialization_FileListResult() { // Arrange @@ -442,9 +444,9 @@ public void Test16_JsonSerialization_FileListResult() }); // Assert - Valid JSON structure - json.Should().Contain("\"files\":"); - json.Should().Contain("\"totalFiles\":"); - json.Should().Contain("\"pattern\":"); + Assert.That(json, Does.Contain("\"files\":")); + Assert.That(json, Does.Contain("\"totalFiles\":")); + Assert.That(json, Does.Contain("\"pattern\":")); // Deserialize back var deserialized = JsonSerializer.Deserialize(json, new JsonSerializerOptions @@ -452,11 +454,11 @@ public void Test16_JsonSerialization_FileListResult() PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); - deserialized.Should().NotBeNull(); - deserialized!.TotalFiles.Should().Be(listResult.TotalFiles); + Assert.That(deserialized, Is.Not.Null); + Assert.That(deserialized!.TotalFiles, Is.EqualTo(listResult.TotalFiles)); } - [Fact] + [Test] public async Task Test17_JsonSerialization_FileReadResult() { // Arrange @@ -471,10 +473,10 @@ public async Task Test17_JsonSerialization_FileReadResult() }); // Assert - json.Should().Contain("\"success\": true"); - json.Should().Contain("\"content\":"); - json.Should().Contain("\"encoding\":"); - json.Should().Contain("\"lineCount\":"); + Assert.That(json, Does.Contain("\"success\": true")); + Assert.That(json, Does.Contain("\"content\":")); + Assert.That(json, Does.Contain("\"encoding\":")); + Assert.That(json, Does.Contain("\"lineCount\":")); // Deserialize back var deserialized = JsonSerializer.Deserialize(json, new JsonSerializerOptions @@ -482,12 +484,12 @@ public async Task Test17_JsonSerialization_FileReadResult() PropertyNamingPolicy = JsonNamingPolicy.CamelCase }); - deserialized.Should().NotBeNull(); - deserialized!.Success.Should().BeTrue(); - deserialized.Content.Should().Be(readResult.Content); + Assert.That(deserialized, Is.Not.Null); + Assert.That(deserialized!.Success, Is.True); + Assert.That(deserialized.Content, Is.EqualTo(readResult.Content)); } - [Fact] + [Test] public async Task Test18_Performance_ListManyFiles() { // Arrange - Create many test files @@ -503,11 +505,11 @@ public async Task Test18_Performance_ListManyFiles() var duration = DateTime.UtcNow - startTime; // Assert - Should be fast - result.TotalFiles.Should().BeGreaterThan(50); - duration.Should().BeLessThan(TimeSpan.FromSeconds(1)); + Assert.That(result.TotalFiles, Is.GreaterThan(50)); + Assert.That(duration, Is.LessThan(TimeSpan.FromSeconds(1))); } - [Fact] + [Test] public async Task Test19_ConcurrentOperations_MultipleReads() { // Arrange @@ -525,11 +527,11 @@ public async Task Test19_ConcurrentOperations_MultipleReads() var results = await Task.WhenAll(tasks); // Assert - All should succeed - results.Should().AllSatisfy(r => r.Success.Should().BeTrue()); - results.Should().HaveCount(4); + Assert.That(results, Has.All.Matches(r => r.Success == true)); + Assert.That(results, Has.Length.EqualTo(4)); } - [Fact] + [Test] public async Task Test20_EdgeCase_EmptyFile() { // Arrange @@ -541,10 +543,10 @@ public async Task Test20_EdgeCase_EmptyFile() var result = await _fileService.ReadFileAsync(fileName); // Assert - result.Success.Should().BeTrue(); - result.Content.Should().BeEmpty(); - result.LineCount.Should().Be(1); // Empty file has 1 line + Assert.That(result.Success, Is.True); + Assert.That(result.Content, Is.Empty); + Assert.That(result.LineCount, Is.EqualTo(1)); // Empty file has 1 line // Note: Size may be > 0 due to UTF-8 BOM, so we just check it's small - result.Size.Should().BeLessThan(10); + Assert.That(result.Size, Is.LessThan(10)); } } diff --git a/tests/MCPsharp.Tests/Integration/McpToolsIntegrationTests.cs b/tests/MCPsharp.Tests/Integration/McpToolsIntegrationTests.cs index aa3fc70..629e536 100644 --- a/tests/MCPsharp.Tests/Integration/McpToolsIntegrationTests.cs +++ b/tests/MCPsharp.Tests/Integration/McpToolsIntegrationTests.cs @@ -52,6 +52,7 @@ protected async Task InitializeServicesAsync() [TearDown] protected override void TearDown() { + _workspace?.Dispose(); base.TearDown(); } diff --git a/tests/MCPsharp.Tests/Integration/Phase2IntegrationTests.cs b/tests/MCPsharp.Tests/Integration/Phase2IntegrationTests.cs index 9ca89a4..daa5740 100644 --- a/tests/MCPsharp.Tests/Integration/Phase2IntegrationTests.cs +++ b/tests/MCPsharp.Tests/Integration/Phase2IntegrationTests.cs @@ -5,7 +5,7 @@ using MCPsharp.Services; using MCPsharp.Services.Phase2; using MCPsharp.Services.Roslyn; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Integration; @@ -13,17 +13,19 @@ namespace MCPsharp.Tests.Integration; /// Phase 2 Integration Tests - Tests complete workflows across multiple Phase 2 features /// These tests create realistic project structures and verify end-to-end functionality /// -[Trait("Category", "Phase2Integration")] -public class Phase2IntegrationTests : IDisposable +[TestFixture] +[Category("Phase2Integration")] +public class Phase2IntegrationTests { - private readonly string _testRoot; - private readonly RoslynWorkspace _workspace; - private readonly ReferenceFinderService _referenceFinder; - private readonly MCPsharp.Services.Phase2.WorkflowAnalyzerService _workflowAnalyzer; - private readonly ConfigAnalyzerService _configAnalyzer; - private readonly ImpactAnalyzerService _impactAnalyzer; - - public Phase2IntegrationTests() + private string _testRoot; + private RoslynWorkspace _workspace; + private ReferenceFinderService _referenceFinder; + private MCPsharp.Services.Phase2.WorkflowAnalyzerService _workflowAnalyzer; + private ConfigAnalyzerService _configAnalyzer; + private ImpactAnalyzerService _impactAnalyzer; + + [SetUp] + public void SetUp() { _testRoot = Path.Combine(Path.GetTempPath(), $"mcpsharp_phase2_tests_{Guid.NewGuid():N}"); Directory.CreateDirectory(_testRoot); @@ -41,17 +43,20 @@ private async Task InitializeWorkspaceForProject(string projectDir) await _workspace.InitializeAsync(projectDir); } - public void Dispose() + [TearDown] + public void TearDown() { if (Directory.Exists(_testRoot)) { Directory.Delete(_testRoot, true); } + + _workspace?.Dispose(); } #region Workflow Analysis Integration Tests - [Fact] + [Test] public async Task WorkflowAnalysis_GetAllWorkflows_ReturnsProjectWorkflows() { // Arrange: Create project with multiple workflows @@ -86,12 +91,12 @@ await File.WriteAllTextAsync(Path.Combine(workflowDir, "deploy.yml"), @" var workflows = await _workflowAnalyzer.GetAllWorkflowsAsync(projectDir); // Assert: Verify workflows are detected - Assert.Equal(2, workflows.Count); - Assert.Contains(workflows, w => w.Name == "CI"); - Assert.Contains(workflows, w => w.Name == "Deploy"); + Assert.That(workflows, Has.Count.EqualTo(2)); + Assert.That(workflows.Any(w => w.Name == "CI"), Is.True); + Assert.That(workflows.Any(w => w.Name == "Deploy"), Is.True); } - [Fact] + [Test] public async Task WorkflowAnalysis_ParseWorkflow_ExtractsCompleteStructure() { // Arrange: Create complex workflow @@ -127,17 +132,17 @@ public async Task WorkflowAnalysis_ParseWorkflow_ExtractsCompleteStructure() var details = await _workflowAnalyzer.ParseWorkflowAsync(workflowPath); // Assert: Verify workflow structure is extracted - Assert.NotNull(details); - Assert.Equal("Complex Build", details.Name); - Assert.NotNull(details.Triggers); - Assert.Contains(details.Triggers, t => t == "push"); - Assert.Contains(details.Triggers, t => t == "pull_request"); - Assert.NotNull(details.Jobs); - Assert.Contains(details.Jobs, j => j.Name == "build"); - Assert.Contains(details.Jobs, j => j.Name == "deploy"); + Assert.That(details, Is.Not.Null); + Assert.That(details.Name, Is.EqualTo("Complex Build")); + Assert.That(details.Triggers, Is.Not.Null); + Assert.That(details.Triggers, Does.Contain("push")); + Assert.That(details.Triggers, Does.Contain("pull_request")); + Assert.That(details.Jobs, Is.Not.Null); + Assert.That(details.Jobs, Has.Some.Matches(j => j.Name == "build")); + Assert.That(details.Jobs, Has.Some.Matches(j => j.Name == "deploy")); } - [Fact] + [Test] public async Task WorkflowAnalysis_ValidateConsistency_DetectsVersionMismatch() { // Arrange: Create project with mismatched .NET versions @@ -167,15 +172,15 @@ await File.WriteAllTextAsync(csprojPath, @" var issues = await _workflowAnalyzer.ValidateWorkflowConsistencyAsync(workflowPath, projectDir); // Assert: Verify version mismatch is detected - Assert.NotEmpty(issues); - Assert.Contains(issues, i => i.Severity.Equals("Warning", StringComparison.OrdinalIgnoreCase) && i.Message.Contains("version mismatch")); + Assert.That(issues, Is.Not.Empty); + Assert.That(issues, Has.Some.Matches(i => i.Severity.Equals("Warning", StringComparison.OrdinalIgnoreCase) && i.Message.Contains("version mismatch"))); } #endregion #region Config Analysis Integration Tests - [Fact] + [Test] public async Task ConfigAnalysis_MergeConfigs_ProducesCorrectHierarchy() { // Arrange: Create config hierarchy @@ -221,29 +226,29 @@ await File.WriteAllTextAsync(Path.Combine(projectDir, "appsettings.Staging.json" var mergedConfig = await _configAnalyzer.MergeConfigsAsync(configPaths); // Assert: Verify merged config hierarchy - Assert.NotNull(mergedConfig); - Assert.Equal(3, mergedConfig.SourceFiles.Count); + Assert.That(mergedConfig, Is.Not.Null); + Assert.That(mergedConfig.SourceFiles, Has.Count.EqualTo(3)); // Check that config merging worked (keys may be in different format) - Assert.True(mergedConfig.MergedSettings.Any()); + Assert.That(mergedConfig.MergedSettings.Any(), Is.True); // Look for keys that should exist after merging var logLevelDefault = mergedConfig.MergedSettings.Keys.FirstOrDefault(k => k.Contains("Default") && k.Contains("Logging")); var logLevelMicrosoft = mergedConfig.MergedSettings.Keys.FirstOrDefault(k => k.Contains("Microsoft") && k.Contains("Logging")); var databaseConnection = mergedConfig.MergedSettings.Keys.FirstOrDefault(k => k.Contains("Database") && k.Contains("Connection")); - Assert.NotNull(logLevelDefault); - Assert.NotNull(logLevelMicrosoft); - Assert.NotNull(databaseConnection); + Assert.That(logLevelDefault, Is.Not.Null); + Assert.That(logLevelMicrosoft, Is.Not.Null); + Assert.That(databaseConnection, Is.Not.Null); // Development config should override default log level to Debug - Assert.Equal("Debug", mergedConfig.MergedSettings[logLevelDefault]); + Assert.That(mergedConfig.MergedSettings[logLevelDefault], Is.EqualTo("Debug")); // Staging config should override connection string - Assert.Equal("Server=staging;", mergedConfig.MergedSettings[databaseConnection]); + Assert.That(mergedConfig.MergedSettings[databaseConnection], Is.EqualTo("Server=staging;")); } - [Fact] + [Test] public async Task ConfigAnalysis_GetSchema_ExtractsStructure() { // Arrange: Create nested config @@ -275,9 +280,9 @@ await File.WriteAllTextAsync(configPath, @"{ var schema = await _configAnalyzer.GetConfigSchemaAsync(configPath); // Assert: Verify schema structure is extracted with types - Assert.NotNull(schema); - Assert.Equal(configPath, schema.FilePath); - Assert.True(schema.Properties.Count > 0); + Assert.That(schema, Is.Not.Null); + Assert.That(schema.FilePath, Is.EqualTo(configPath)); + Assert.That(schema.Properties, Is.Not.Empty); // Verify nested structure extraction (handle potential double prefixing) var dbConnectionString = schema.Properties.Keys.FirstOrDefault(k => k.Contains("ConnectionString")); @@ -285,23 +290,23 @@ await File.WriteAllTextAsync(configPath, @"{ var dbTimeout = schema.Properties.Keys.FirstOrDefault(k => k.Contains("Timeout")); var dbEnableRetry = schema.Properties.Keys.FirstOrDefault(k => k.Contains("EnableRetry")); - Assert.NotNull(dbConnectionString); - Assert.NotNull(dbMaxConnections); - Assert.NotNull(dbTimeout); - Assert.NotNull(dbEnableRetry); + Assert.That(dbConnectionString, Is.Not.Null); + Assert.That(dbMaxConnections, Is.Not.Null); + Assert.That(dbTimeout, Is.Not.Null); + Assert.That(dbEnableRetry, Is.Not.Null); // Verify type detection - Assert.Equal("string", schema.Properties[dbConnectionString].Type); - Assert.Equal("integer", schema.Properties[dbMaxConnections].Type); - Assert.Equal("integer", schema.Properties[dbTimeout].Type); - Assert.Equal("boolean", schema.Properties[dbEnableRetry].Type); + Assert.That(schema.Properties[dbConnectionString].Type, Is.EqualTo("string")); + Assert.That(schema.Properties[dbMaxConnections].Type, Is.EqualTo("integer")); + Assert.That(schema.Properties[dbTimeout].Type, Is.EqualTo("integer")); + Assert.That(schema.Properties[dbEnableRetry].Type, Is.EqualTo("boolean")); } #endregion #region Impact Analysis Integration Tests - [Fact] + [Test] public async Task ImpactAnalysis_ModelChange_DetectsMultiFileImpact() { // Arrange: Create multi-layer architecture @@ -386,17 +391,17 @@ public IActionResult Create(User user) var result = await _impactAnalyzer.AnalyzeImpactAsync(change); // Assert: Verify all affected files are detected - Assert.NotNull(result); - Assert.True(result.TotalImpactedFiles > 0); + Assert.That(result, Is.Not.Null); + Assert.That(result.TotalImpactedFiles > 0, Is.True); // Should detect impacts in related C# files var csharpImpacts = result.CSharpImpacts.Select(i => Path.GetFileName(i.FilePath)).ToList(); - Assert.Contains("UserRepository.cs", csharpImpacts); - Assert.Contains("UserService.cs", csharpImpacts); - Assert.Contains("UserController.cs", csharpImpacts); + Assert.That(csharpImpacts, Does.Contain("UserRepository.cs")); + Assert.That(csharpImpacts, Does.Contain("UserService.cs")); + Assert.That(csharpImpacts, Does.Contain("UserController.cs")); } - [Fact] + [Test] public async Task ImpactAnalysis_InterfaceChange_DetectsImplementations() { // Arrange: Create interface with multiple implementations @@ -443,18 +448,18 @@ public class PaymentService var result = await _impactAnalyzer.AnalyzeImpactAsync(change); // Assert: Verify both implementations and callers are detected - Assert.NotNull(result); - Assert.True(result.TotalImpactedFiles > 0); + Assert.That(result, Is.Not.Null); + Assert.That(result.TotalImpactedFiles > 0, Is.True); // Should detect both implementations var csharpImpacts = result.CSharpImpacts.Select(i => Path.GetFileName(i.FilePath)).ToList(); - Assert.Contains("CreditCardProcessor.cs", csharpImpacts); - Assert.Contains("PayPalProcessor.cs", csharpImpacts); - Assert.Contains("PaymentService.cs", csharpImpacts); + Assert.That(csharpImpacts, Does.Contain("CreditCardProcessor.cs")); + Assert.That(csharpImpacts, Does.Contain("PayPalProcessor.cs")); + Assert.That(csharpImpacts, Does.Contain("PaymentService.cs")); } - [Fact] + [Test] public async Task ImpactAnalysis_ConfigChange_DetectsCodeReferences() { // Arrange: Create service referencing config @@ -496,23 +501,23 @@ public void SendEmail(string to, string subject) var result = await _impactAnalyzer.AnalyzeImpactAsync(change); // Assert: Verify EmailService.cs is detected as affected - Assert.NotNull(result); - Assert.True(result.TotalImpactedFiles > 0); + Assert.That(result, Is.Not.Null); + Assert.That(result.TotalImpactedFiles > 0, Is.True); // Should detect config impacts var configImpacts = result.ConfigImpacts.Select(i => Path.GetFileName(i.FilePath)).ToList(); - Assert.Contains("appsettings.json", configImpacts); + Assert.That(configImpacts, Does.Contain("appsettings.json")); // Should detect code references to config var csharpImpacts = result.CSharpImpacts.Select(i => Path.GetFileName(i.FilePath)).ToList(); - Assert.Contains("EmailService.cs", csharpImpacts); + Assert.That(csharpImpacts, Does.Contain("EmailService.cs")); } #endregion #region Feature Tracing Integration Tests - [Fact] + [Test] public async Task FeatureTracing_DiscoverComponents_FindsCompleteFeature() { // Arrange: Create complete feature @@ -572,12 +577,12 @@ public IActionResult Create(Product product) await File.WriteAllTextAsync(Path.Combine(testsDir, "ProductServiceTests.cs"), @" public class ProductServiceTests { - [Fact] + [Test] public void GetProduct_ReturnsProduct() { var service = new ProductService(new ProductRepository()); var product = service.GetProduct(1); - Assert.NotNull(product); + Assert.That(product); } }"); @@ -604,7 +609,7 @@ await File.WriteAllTextAsync(Path.Combine(docsDir, "Products.md"), @"# Product A // Model, Repository, Service, Controller, Tests, Config, Docs } - [Fact] + [Test] public async Task FeatureTracing_TraceFeature_BuildsDependencyGraph() { // Arrange: Create multi-layer feature @@ -651,7 +656,7 @@ await File.WriteAllTextAsync(Path.Combine(srcDir, "Controller.cs"), #region Cross-Feature Integration Tests - [Fact] + [Test] public async Task PolyglotAnalysis_TracksAcrossAllFileTypes() { // Arrange: Create polyglot project with C#, JSON, YAML, Markdown @@ -718,28 +723,28 @@ await File.WriteAllTextAsync(Path.Combine(docsDir, "Payments.md"), @"# Payment P var result = await _impactAnalyzer.AnalyzeImpactAsync(change); // Assert: Verify polyglot impact detection - Assert.NotNull(result); - Assert.True(result.TotalImpactedFiles > 0); + Assert.That(result, Is.Not.Null); + Assert.That(result.TotalImpactedFiles > 0, Is.True); // Should detect impacts in C# files var csharpFiles = result.CSharpImpacts.Select(i => Path.GetFileName(i.FilePath)).ToList(); - Assert.Contains("PaymentService.cs", csharpFiles); + Assert.That(csharpFiles, Does.Contain("PaymentService.cs")); // Should detect impacts in config files var configFiles = result.ConfigImpacts.Select(i => Path.GetFileName(i.FilePath)).ToList(); Console.WriteLine($"[TEST DEBUG] Config files found: [{string.Join(", ", configFiles)}]"); - Assert.Contains("appsettings.json", configFiles); + Assert.That(configFiles, Does.Contain("appsettings.json")); // Should detect impacts in workflow files var workflowFiles = result.WorkflowImpacts.Select(i => Path.GetFileName(i.FilePath)).ToList(); - Assert.Contains("payment-tests.yml", workflowFiles); + Assert.That(workflowFiles, Does.Contain("payment-tests.yml")); // Should detect impacts in documentation var docFiles = result.DocumentationImpacts.Select(i => Path.GetFileName(i.FilePath)).ToList(); - Assert.Contains("Payments.md", docFiles); + Assert.That(docFiles, Does.Contain("Payments.md")); } - [Fact] + [Test] public async Task CompleteWorkflow_AnalyzeProjectStructure() { // Arrange: Create realistic project @@ -786,18 +791,11 @@ await File.WriteAllTextAsync(Path.Combine(srcDir, "Service.cs"), await File.WriteAllTextAsync(Path.Combine(testsDir, "ServiceTests.cs"), "public class ServiceTests { [Fact] public void Test() { } }"); - // Act: Perform various analyses - var workflowsTask = Assert.ThrowsAsync(async () => - await _workflowAnalyzer.GetAllWorkflowsAsync(projectDir)); - - // NOTE: ConfigAnalyzerService and WorkflowAnalyzerService are now implemented, FeatureTracerService is not - // WorkflowAnalyzerService and ConfigAnalyzerService should work now - // await workflowsTask; // This should NOT throw anymore - - // NOTE: These services are now functional - tests should be updated - // TODO: Update this test to verify actual functionality instead of expecting NotImplementedException + // Act: Perform workflow analysis + var workflows = await _workflowAnalyzer.GetAllWorkflowsAsync(projectDir); - // TODO: Once implemented, verify complete project analysis + // Assert: Verify workflows were found and analyzed + Assert.That(workflows, Is.Not.Empty, "Should find workflows in the project"); } #endregion diff --git a/tests/MCPsharp.Tests/Integration/ReverseSearchMcpToolsTests.cs b/tests/MCPsharp.Tests/Integration/ReverseSearchMcpToolsTests.cs index 4785826..549b1e6 100644 --- a/tests/MCPsharp.Tests/Integration/ReverseSearchMcpToolsTests.cs +++ b/tests/MCPsharp.Tests/Integration/ReverseSearchMcpToolsTests.cs @@ -3,20 +3,22 @@ using MCPsharp.Services; using MCPsharp.Services.Roslyn; using MCPsharp.Tests.TestFixtures; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Integration; /// /// Integration tests for reverse search MCP tools /// -public class ReverseSearchMcpToolsTests : IDisposable +[TestFixture] +public class ReverseSearchMcpToolsTests { - private readonly ProjectContextManager _projectContext; - private readonly RoslynWorkspace _workspace; - private readonly McpToolRegistry _toolRegistry; + private ProjectContextManager _projectContext; + private RoslynWorkspace _workspace; + private McpToolRegistry _toolRegistry; - public ReverseSearchMcpToolsTests() + [SetUp] + public void SetUp() { _projectContext = new ProjectContextManager(); _workspace = new RoslynWorkspace(); @@ -88,26 +90,26 @@ public void Run() _projectContext.OpenProject(testDir); } - [Fact] + [Test] public void ToolRegistry_ShouldContainReverseSearchTools() { // Act var tools = _toolRegistry.GetTools(); // Assert - Assert.Contains(tools, t => t.Name == "find_callers"); - Assert.Contains(tools, t => t.Name == "find_call_chains"); - Assert.Contains(tools, t => t.Name == "find_type_usages"); - Assert.Contains(tools, t => t.Name == "analyze_call_patterns"); - Assert.Contains(tools, t => t.Name == "analyze_inheritance"); - Assert.Contains(tools, t => t.Name == "find_circular_dependencies"); - Assert.Contains(tools, t => t.Name == "find_unused_methods"); - Assert.Contains(tools, t => t.Name == "analyze_call_graph"); - Assert.Contains(tools, t => t.Name == "find_recursive_calls"); - Assert.Contains(tools, t => t.Name == "analyze_type_dependencies"); + Assert.That(tools, Does.Contain(tools.FirstOrDefault(t => t.Name == "find_callers"))); + Assert.That(tools, Does.Contain(tools.FirstOrDefault(t => t.Name == "find_call_chains"))); + Assert.That(tools, Does.Contain(tools.FirstOrDefault(t => t.Name == "find_type_usages"))); + Assert.That(tools, Does.Contain(tools.FirstOrDefault(t => t.Name == "analyze_call_patterns"))); + Assert.That(tools, Does.Contain(tools.FirstOrDefault(t => t.Name == "analyze_inheritance"))); + Assert.That(tools, Does.Contain(tools.FirstOrDefault(t => t.Name == "find_circular_dependencies"))); + Assert.That(tools, Does.Contain(tools.FirstOrDefault(t => t.Name == "find_unused_methods"))); + Assert.That(tools, Does.Contain(tools.FirstOrDefault(t => t.Name == "analyze_call_graph"))); + Assert.That(tools, Does.Contain(tools.FirstOrDefault(t => t.Name == "find_recursive_calls"))); + Assert.That(tools, Does.Contain(tools.FirstOrDefault(t => t.Name == "analyze_type_dependencies"))); } - [Fact] + [Test] public async Task ExecuteFindCallers_ShouldReturnCallers() { // Arrange @@ -127,12 +129,12 @@ public async Task ExecuteFindCallers_ShouldReturnCallers() Console.WriteLine($"Result: {result.Result?.GetType().Name ?? "null"}"); // Assert - Assert.True(result.Success, $"Expected success but got: {result.Error}"); - Assert.NotNull(result.Result); - Assert.True(result.Error == null, $"Expected null error but got: '{result.Error}'"); + Assert.That(result.Success, Is.True, $"Expected success but got: {result.Error}"); + Assert.That(result.Result, Is.Not.Null); + Assert.That(result.Error, Is.Null, $"Expected null error but got: '{result.Error}'"); } - [Fact] + [Test] public async Task ExecuteFindCallChains_ShouldReturnCallChains() { // Arrange @@ -148,12 +150,12 @@ public async Task ExecuteFindCallChains_ShouldReturnCallChains() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_call_chains", Arguments = arguments }); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); - Assert.Null(result.Error); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); + Assert.That(result.Error, Is.Null); } - [Fact] + [Test] public async Task ExecuteFindTypeUsages_ShouldReturnTypeUsages() { // Arrange @@ -166,12 +168,12 @@ public async Task ExecuteFindTypeUsages_ShouldReturnTypeUsages() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_type_usages", Arguments = arguments }); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); - Assert.Null(result.Error); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); + Assert.That(result.Error, Is.Null); } - [Fact] + [Test] public async Task ExecuteAnalyzeCallPatterns_ShouldReturnPatternAnalysis() { // Arrange @@ -185,12 +187,12 @@ public async Task ExecuteAnalyzeCallPatterns_ShouldReturnPatternAnalysis() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "analyze_call_patterns", Arguments = arguments }); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); - Assert.Null(result.Error); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); + Assert.That(result.Error, Is.Null); } - [Fact] + [Test] public async Task ExecuteAnalyzeInheritance_ShouldReturnInheritanceAnalysis() { // Arrange @@ -203,12 +205,12 @@ public async Task ExecuteAnalyzeInheritance_ShouldReturnInheritanceAnalysis() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "analyze_inheritance", Arguments = arguments }); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); - Assert.Null(result.Error); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); + Assert.That(result.Error, Is.Null); } - [Fact] + [Test] public async Task ExecuteFindCircularDependencies_ShouldReturnDependencies() { // Arrange @@ -221,12 +223,12 @@ public async Task ExecuteFindCircularDependencies_ShouldReturnDependencies() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_circular_dependencies", Arguments = arguments }); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); - Assert.Null(result.Error); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); + Assert.That(result.Error, Is.Null); } - [Fact] + [Test] public async Task ExecuteFindUnusedMethods_ShouldReturnUnusedMethods() { // Arrange @@ -239,12 +241,12 @@ public async Task ExecuteFindUnusedMethods_ShouldReturnUnusedMethods() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_unused_methods", Arguments = arguments }); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); - Assert.Null(result.Error); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); + Assert.That(result.Error, Is.Null); } - [Fact] + [Test] public async Task ExecuteAnalyzeCallGraph_ShouldReturnCallGraph() { // Arrange @@ -257,12 +259,12 @@ public async Task ExecuteAnalyzeCallGraph_ShouldReturnCallGraph() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "analyze_call_graph", Arguments = arguments }); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); - Assert.Null(result.Error); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); + Assert.That(result.Error, Is.Null); } - [Fact] + [Test] public async Task ExecuteFindRecursiveCalls_ShouldReturnRecursiveCalls() { // Arrange @@ -277,12 +279,12 @@ public async Task ExecuteFindRecursiveCalls_ShouldReturnRecursiveCalls() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_recursive_calls", Arguments = arguments }); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); - Assert.Null(result.Error); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); + Assert.That(result.Error, Is.Null); } - [Fact] + [Test] public async Task ExecuteAnalyzeTypeDependencies_ShouldReturnDependencies() { // Arrange @@ -295,12 +297,12 @@ public async Task ExecuteAnalyzeTypeDependencies_ShouldReturnDependencies() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "analyze_type_dependencies", Arguments = arguments }); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); - Assert.Null(result.Error); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); + Assert.That(result.Error, Is.Null); } - [Fact] + [Test] public async Task ExecuteFindCallers_WithInvalidArguments_ShouldReturnError() { // Arrange @@ -310,12 +312,12 @@ public async Task ExecuteFindCallers_WithInvalidArguments_ShouldReturnError() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_callers", Arguments = arguments }); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("MethodName is required", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("MethodName is required")); } - [Fact] + [Test] public async Task ExecuteFindTypeUsages_WithInvalidArguments_ShouldReturnError() { // Arrange @@ -325,12 +327,12 @@ public async Task ExecuteFindTypeUsages_WithInvalidArguments_ShouldReturnError() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_type_usages", Arguments = arguments }); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("TypeName is required", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("TypeName is required")); } - [Fact] + [Test] public async Task ExecuteAnalyzeInheritance_WithInvalidArguments_ShouldReturnError() { // Arrange @@ -340,12 +342,12 @@ public async Task ExecuteAnalyzeInheritance_WithInvalidArguments_ShouldReturnErr var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "analyze_inheritance", Arguments = arguments }); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("TypeName is required", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("TypeName is required")); } - [Fact] + [Test] public async Task ExecuteUnknownTool_ShouldReturnError() { // Arrange @@ -355,12 +357,12 @@ public async Task ExecuteUnknownTool_ShouldReturnError() var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "unknown_tool", Arguments = arguments }); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Unknown tool", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Unknown tool")); } - [Fact] + [Test] public void ReverseSearchTools_ShouldHaveCorrectInputSchemas() { // Act @@ -368,12 +370,12 @@ public void ReverseSearchTools_ShouldHaveCorrectInputSchemas() var findCallersTool = tools.FirstOrDefault(t => t.Name == "find_callers"); // Assert - Assert.NotNull(findCallersTool); - Assert.NotNull(findCallersTool.InputSchema); - Assert.Equal("Find all methods that call a specific method using call graph analysis. PREFERRED over grep/search for understanding code flow and dependencies. Returns structured caller information with file and line locations. Use to analyze method dependencies before refactoring or to trace execution paths.", findCallersTool.Description); + Assert.That(findCallersTool, Is.Not.Null); + Assert.That(findCallersTool.InputSchema, Is.Not.Null); + Assert.That(findCallersTool.Description, Is.EqualTo("Find all methods that call a specific method using call graph analysis. PREFERRED over grep/search for understanding code flow and dependencies. Returns structured caller information with file and line locations. Use to analyze method dependencies before refactoring or to trace execution paths.")); } - [Fact] + [Test] public void ReverseSearchTools_ShouldHaveValidSchemas() { // Act @@ -386,16 +388,16 @@ public void ReverseSearchTools_ShouldHaveValidSchemas() t.Name == "find_recursive_calls").ToList(); // Assert - Assert.True(reverseSearchTools.Count >= 10); - Assert.All(reverseSearchTools, tool => + Assert.That(reverseSearchTools.Count, Is.GreaterThanOrEqualTo(10)); + foreach (var tool in reverseSearchTools) { - Assert.NotNull(tool.Name); - Assert.NotNull(tool.Description); - Assert.NotNull(tool.InputSchema); - }); + Assert.That(tool.Name, Is.Not.Null); + Assert.That(tool.Description, Is.Not.Null); + Assert.That(tool.InputSchema, Is.Not.Null); + } } - [Fact] + [Test] public async Task ExecuteFindCallChains_WithDirectionParameter_ShouldAcceptValidValues() { // Test backward direction @@ -406,7 +408,7 @@ public async Task ExecuteFindCallChains_WithDirectionParameter_ShouldAcceptValid }"); var backwardResult = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_call_chains", Arguments = backwardArgs }); - Assert.True(backwardResult.Success); + Assert.That(backwardResult.Success, Is.True); // Test forward direction var forwardArgs = JsonDocument.Parse(@" @@ -416,10 +418,10 @@ public async Task ExecuteFindCallChains_WithDirectionParameter_ShouldAcceptValid }"); var forwardResult = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_call_chains", Arguments = forwardArgs }); - Assert.True(forwardResult.Success); + Assert.That(forwardResult.Success, Is.True); } - [Fact] + [Test] public async Task ExecuteFindCallChains_WithMaxDepthParameter_ShouldAcceptValidValues() { // Arrange @@ -433,11 +435,11 @@ public async Task ExecuteFindCallChains_WithMaxDepthParameter_ShouldAcceptValidV var result = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_call_chains", Arguments = arguments }); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); } - [Fact] + [Test] public async Task ExecuteMultipleTools_Sequentially_ShouldWorkCorrectly() { // Act - Execute multiple tools in sequence @@ -448,7 +450,7 @@ public async Task ExecuteMultipleTools_Sequentially_ShouldWorkCorrectly() }"); var callersResult = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_callers", Arguments = callersArgs }); - Assert.True(callersResult.Success); + Assert.That(callersResult.Success, Is.True); var typeUsagesArgs = JsonDocument.Parse(@" { @@ -456,7 +458,7 @@ public async Task ExecuteMultipleTools_Sequentially_ShouldWorkCorrectly() }"); var typeUsagesResult = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "find_type_usages", Arguments = typeUsagesArgs }); - Assert.True(typeUsagesResult.Success); + Assert.That(typeUsagesResult.Success, Is.True); var patternsArgs = JsonDocument.Parse(@" { @@ -465,10 +467,11 @@ public async Task ExecuteMultipleTools_Sequentially_ShouldWorkCorrectly() }"); var patternsResult = await _toolRegistry.ExecuteTool(new ToolCallRequest { Name = "analyze_call_patterns", Arguments = patternsArgs }); - Assert.True(patternsResult.Success); + Assert.That(patternsResult.Success, Is.True); } - public void Dispose() + [TearDown] + public void TearDown() { var context = _projectContext.GetProjectContext(); if (context != null && Directory.Exists(context.RootPath)) @@ -483,6 +486,6 @@ public void Dispose() } } - // RoslynWorkspace and ProjectContext no longer implement IDisposable + _workspace?.Dispose(); } } \ No newline at end of file diff --git a/tests/MCPsharp.Tests/Integration/RoslynAnalyzerIntegrationTests.cs b/tests/MCPsharp.Tests/Integration/RoslynAnalyzerIntegrationTests.cs index 3c62dee..6ef293c 100644 --- a/tests/MCPsharp.Tests/Integration/RoslynAnalyzerIntegrationTests.cs +++ b/tests/MCPsharp.Tests/Integration/RoslynAnalyzerIntegrationTests.cs @@ -292,8 +292,8 @@ public void AnalyzerDiscovery_LoadFromAssembly_SuccessfullyLoadsAnalyzers() recursive: false); // Assert: Should find some assemblies (at minimum the test assembly) - Assert.That(discoveredPaths, Is.Not.Null); // Note: May not find actual analyzer assemblies in test environment + Assert.That(discoveredPaths.Length, Is.GreaterThanOrEqualTo(0)); } [Test] @@ -307,7 +307,6 @@ public async Task AnalyzerDiscovery_LoadInvalidAssembly_HandlesGracefully() fakeAssemblyPath); // Assert: Should return empty array, not throw - Assert.That(loadedAnalyzers, Is.Not.Null); Assert.That(loadedAnalyzers.IsEmpty, Is.True); } @@ -562,7 +561,6 @@ public async Task Health_GetAnalyzerHealth_ReturnsValidStatus() var healthStatuses = await _analyzerHost.GetHealthStatusAsync(); // Assert: Should have health status for loaded analyzer - Assert.That(healthStatuses, Is.Not.Null); Assert.That(healthStatuses.Length, Is.GreaterThan(0)); var analyzerHealth = healthStatuses.FirstOrDefault(h => h.AnalyzerId == adapter.Id); diff --git a/tests/MCPsharp.Tests/Integration/SqliteCacheIntegrationTests.cs b/tests/MCPsharp.Tests/Integration/SqliteCacheIntegrationTests.cs index 1698646..91f9e8a 100644 --- a/tests/MCPsharp.Tests/Integration/SqliteCacheIntegrationTests.cs +++ b/tests/MCPsharp.Tests/Integration/SqliteCacheIntegrationTests.cs @@ -1,5 +1,4 @@ using NUnit.Framework; -using FluentAssertions; using MCPsharp.Services; using MCPsharp.Services.Database; using MCPsharp.Models; @@ -77,13 +76,13 @@ public async Task FullWorkflow_ProjectOpenToResourceQuery() var result = await _resourceRegistry.ReadResourceAsync("project://overview"); // Assert - result.Contents.Should().HaveCount(1); - result.Contents[0].Text.Should().Contain("Project Overview"); - result.Contents[0].MimeType.Should().Be("text/markdown"); + Assert.That(result.Contents, Has.Count.EqualTo(1)); + Assert.That(result.Contents[0].Text, Does.Contain("Project Overview")); + Assert.That(result.Contents[0].MimeType, Is.EqualTo("text/markdown")); // Note: ResourceContentGenerators expects "root_path" but ProjectContextManager returns "rootPath" // This test documents the current behavior - the resource shows "no project" message // until the field name mismatch is fixed in production code - result.Contents[0].Text.Should().Contain("project"); + Assert.That(result.Contents[0].Text, Does.Contain("project")); } [Test] @@ -134,21 +133,21 @@ public async Task Database_PersistsSymbolsAcrossOperations() var foundSymbols = await _database.FindSymbolsByNameAsync("Test"); // Assert - foundSymbols.Should().HaveCount(2); - foundSymbols.Select(s => s.Name).Should().Contain("TestClass"); - foundSymbols.Select(s => s.Name).Should().Contain("TestMethod"); + Assert.That(foundSymbols, Has.Count.EqualTo(2)); + Assert.That(foundSymbols.Any(s => s.Name == "TestClass"), Is.True); + Assert.That(foundSymbols.Any(s => s.Name == "TestMethod"), Is.True); // Verify class details var testClass = foundSymbols.First(s => s.Name == "TestClass"); - testClass.Kind.Should().Be("Class"); - testClass.Namespace.Should().Be("TestNamespace"); - testClass.Accessibility.Should().Be("public"); + Assert.That(testClass.Kind, Is.EqualTo("Class")); + Assert.That(testClass.Namespace, Is.EqualTo("TestNamespace")); + Assert.That(testClass.Accessibility, Is.EqualTo("public")); // Verify method details var testMethod = foundSymbols.First(s => s.Name == "TestMethod"); - testMethod.Kind.Should().Be("Method"); - testMethod.ContainingType.Should().Be("TestClass"); - testMethod.Signature.Should().Be("void TestMethod()"); + Assert.That(testMethod.Kind, Is.EqualTo("Method")); + Assert.That(testMethod.ContainingType, Is.EqualTo("TestClass")); + Assert.That(testMethod.Signature, Is.EqualTo("void TestMethod()")); } [Test] @@ -206,14 +205,14 @@ public async Task Database_CallChainAnalysis() var callChain = await _database.GetCallChainAsync(idA, ProjectDatabase.CallChainDirection.Forward, 5); // Assert - callChain.Should().HaveCountGreaterOrEqualTo(2); // B and C - callChain.Select(s => s.Name).Should().Contain("MethodB"); - callChain.Select(s => s.Name).Should().Contain("MethodC"); + Assert.That(callChain, Has.Count.GreaterThanOrEqualTo(2)); // B and C + Assert.That(callChain.Any(s => s.Name == "MethodB"), Is.True); + Assert.That(callChain.Any(s => s.Name == "MethodC"), Is.True); // Verify backward call chain from C var backwardChain = await _database.GetCallChainAsync(idC, ProjectDatabase.CallChainDirection.Backward, 5); - backwardChain.Select(s => s.Name).Should().Contain("MethodA"); - backwardChain.Select(s => s.Name).Should().Contain("MethodB"); + Assert.That(backwardChain.Any(s => s.Name == "MethodA"), Is.True); + Assert.That(backwardChain.Any(s => s.Name == "MethodB"), Is.True); } [Test] @@ -227,19 +226,19 @@ public void Prompts_ProvidePracticalGuidance() new Dictionary { { "issue", "null reference exception" } }); // Assert - Prompts contain practical guidance - analyzePrompt.Messages[0].Content.Text.Should().Contain("find_symbol"); - analyzePrompt.Messages[0].Content.Text.Should().Contain("semantic"); + Assert.That(analyzePrompt.Messages[0].Content.Text, Does.Contain("find_symbol")); + Assert.That(analyzePrompt.Messages[0].Content.Text, Does.Contain("semantic")); - implementPrompt.Messages[0].Content.Text.Should().Contain("user authentication"); - implementPrompt.Messages[0].Content.Text.Should().Contain("find_symbol"); + Assert.That(implementPrompt.Messages[0].Content.Text, Does.Contain("user authentication")); + Assert.That(implementPrompt.Messages[0].Content.Text, Does.Contain("find_symbol")); - fixPrompt.Messages[0].Content.Text.Should().Contain("null reference exception"); - fixPrompt.Messages[0].Content.Text.Should().Contain("find_call_chains"); + Assert.That(fixPrompt.Messages[0].Content.Text, Does.Contain("null reference exception")); + Assert.That(fixPrompt.Messages[0].Content.Text, Does.Contain("find_call_chains")); // Verify prompt structure - analyzePrompt.Messages.Should().HaveCount(1); - analyzePrompt.Messages[0].Role.Should().Be("user"); - analyzePrompt.Messages[0].Content.Type.Should().Be("text"); + Assert.That(analyzePrompt.Messages, Has.Count.EqualTo(1)); + Assert.That(analyzePrompt.Messages[0].Role, Is.EqualTo("user")); + Assert.That(analyzePrompt.Messages[0].Content.Type, Is.EqualTo("text")); } [Test] @@ -262,14 +261,14 @@ public void Resources_ListAllAvailable() var result = _resourceRegistry.ListResources(); // Assert - result.Resources.Should().HaveCount(3); - result.Resources.Select(r => r.Uri).Should().Contain("project://overview"); - result.Resources.Select(r => r.Uri).Should().Contain("project://structure"); - result.Resources.Select(r => r.Uri).Should().Contain("project://guidance"); + Assert.That(result.Resources, Has.Count.EqualTo(3)); + Assert.That(result.Resources.Any(r => r.Uri == "project://overview"), Is.True); + Assert.That(result.Resources.Any(r => r.Uri == "project://structure"), Is.True); + Assert.That(result.Resources.Any(r => r.Uri == "project://guidance"), Is.True); // Verify resources are ordered var uris = result.Resources.Select(r => r.Uri).ToList(); - uris.Should().BeInAscendingOrder(); + Assert.That(uris, Is.Ordered); } [Test] @@ -296,12 +295,12 @@ public async Task Database_StaleFileDetection() new HashSet { "file1.cs", "file2.cs" }); // Assert - staleFiles.Select(f => f.RelativePath).Should().Contain("file2.cs"); - staleFiles.Select(f => f.RelativePath).Should().NotContain("file1.cs"); + Assert.That(staleFiles.Any(f => f.RelativePath == "file2.cs"), Is.True); + Assert.That(staleFiles.Any(f => f.RelativePath == "file1.cs"), Is.False); - deletedFiles.Select(f => f.RelativePath).Should().Contain("file3.cs"); - deletedFiles.Select(f => f.RelativePath).Should().NotContain("file1.cs"); - deletedFiles.Select(f => f.RelativePath).Should().NotContain("file2.cs"); + Assert.That(deletedFiles.Any(f => f.RelativePath == "file3.cs"), Is.True); + Assert.That(deletedFiles.Any(f => f.RelativePath == "file1.cs"), Is.False); + Assert.That(deletedFiles.Any(f => f.RelativePath == "file2.cs"), Is.False); } [Test] @@ -321,12 +320,12 @@ public async Task Database_ProjectStructureKeyValue() var keys = await _database.GetProjectStructureKeysAsync(projectId); // Assert - retrieved.Should().Be(solutionInfo); - keys.Should().Contain("solution_info"); + Assert.That(retrieved, Is.EqualTo(solutionInfo)); + Assert.That(keys.Contains("solution_info"), Is.True); // Verify the JSON can be deserialized var deserialized = JsonSerializer.Deserialize>(retrieved!); - deserialized.Should().NotBeNull(); + Assert.That(deserialized, Is.Not.Null); } [Test] @@ -344,23 +343,23 @@ public async Task ResourceContentGenerators_GenerateAllResources() var guidance = generators.GenerateGuidance(); // Assert - All resources generate valid content - overview.Uri.Should().Be("project://overview"); - overview.MimeType.Should().Be("text/markdown"); - overview.Text.Should().NotBeNullOrEmpty(); + Assert.That(overview.Uri, Is.EqualTo("project://overview")); + Assert.That(overview.MimeType, Is.EqualTo("text/markdown")); + Assert.That(overview.Text, Is.Not.Null.And.Not.Empty); // Note: Field name mismatch means project info may not be shown - overview.Text.Should().Contain("Project Overview"); + Assert.That(overview.Text, Does.Contain("Project Overview")); - structure.Uri.Should().Be("project://structure"); - structure.Text.Should().Contain("Project Structure"); + Assert.That(structure.Uri, Is.EqualTo("project://structure")); + Assert.That(structure.Text, Does.Contain("Project Structure")); - dependencies.Uri.Should().Be("project://dependencies"); - dependencies.Text.Should().Contain("Dependencies"); + Assert.That(dependencies.Uri, Is.EqualTo("project://dependencies")); + Assert.That(dependencies.Text, Does.Contain("Dependencies")); - symbols.Uri.Should().Be("project://symbols"); - symbols.Text.Should().Contain("Symbols Summary"); + Assert.That(symbols.Uri, Is.EqualTo("project://symbols")); + Assert.That(symbols.Text, Does.Contain("Symbols Summary")); - guidance.Uri.Should().Be("project://guidance"); - guidance.Text.Should().Contain("Usage Guide"); + Assert.That(guidance.Uri, Is.EqualTo("project://guidance")); + Assert.That(guidance.Text, Does.Contain("Usage Guide")); } [Test] @@ -415,16 +414,16 @@ public async Task Integration_FullProjectAnalysisWorkflow() var projectInfo = _projectManager.GetProjectInfo(); // Assert - Verify integrated workflow - symbolSearch.Should().HaveCount(2); - symbolSearch.Any(s => s.Name == "UserService").Should().BeTrue(); - symbolSearch.Any(s => s.Name == "GetUser").Should().BeTrue(); + Assert.That(symbolSearch, Has.Count.EqualTo(2)); + Assert.That(symbolSearch.Any(s => s.Name == "UserService"), Is.True); + Assert.That(symbolSearch.Any(s => s.Name == "GetUser"), Is.True); // Note: Field name mismatch means project name may not be shown - resourceRead.Contents[0].Text.Should().Contain("Project Overview"); + Assert.That(resourceRead.Contents[0].Text, Does.Contain("Project Overview")); - projectInfo.Should().NotBeNull(); - projectInfo!["rootPath"].Should().Be(_testProjectPath); - projectInfo["fileCount"].Should().BeOfType(); + Assert.That(projectInfo, Is.Not.Null); + Assert.That(projectInfo!["rootPath"], Is.EqualTo(_testProjectPath)); + Assert.That(projectInfo["fileCount"], Is.TypeOf()); } [Test] @@ -483,13 +482,13 @@ public async Task Database_FindCallersAndCallees() var callees = await _database.FindCalleesAsync(targetId); // Assert - callers.Should().HaveCount(1); - callers[0].Caller.Name.Should().Be("Caller"); - callers[0].Reference.ReferenceKind.Should().Be("Call"); + Assert.That(callers, Has.Count.EqualTo(1)); + Assert.That(callers[0].Caller.Name, Is.EqualTo("Caller")); + Assert.That(callers[0].Reference.ReferenceKind, Is.EqualTo("Call")); - callees.Should().HaveCount(1); - callees[0].Callee.Name.Should().Be("Callee"); - callees[0].Reference.ReferenceKind.Should().Be("Call"); + Assert.That(callees, Has.Count.EqualTo(1)); + Assert.That(callees[0].Callee.Name, Is.EqualTo("Callee")); + Assert.That(callees[0].Reference.ReferenceKind, Is.EqualTo("Call")); } [Test] @@ -499,14 +498,14 @@ public void PromptRegistry_ListsAllBuiltInPrompts() var result = _promptRegistry.ListPrompts(); // Assert - result.Prompts.Should().HaveCountGreaterOrEqualTo(3); - result.Prompts.Any(p => p.Name == "analyze-codebase").Should().BeTrue(); - result.Prompts.Any(p => p.Name == "implement-feature").Should().BeTrue(); - result.Prompts.Any(p => p.Name == "fix-bug").Should().BeTrue(); + Assert.That(result.Prompts, Has.Count.GreaterThanOrEqualTo(3)); + Assert.That(result.Prompts.Any(p => p.Name == "analyze-codebase"), Is.True); + Assert.That(result.Prompts.Any(p => p.Name == "implement-feature"), Is.True); + Assert.That(result.Prompts.Any(p => p.Name == "fix-bug"), Is.True); // Verify prompts are ordered var names = result.Prompts.Select(p => p.Name).ToList(); - names.Should().BeInAscendingOrder(); + Assert.That(names, Is.Ordered); } [Test] @@ -521,9 +520,9 @@ public async Task Database_HandlesEmptyQueries() var files = await _database.GetAllFilesAsync(projectId); // Assert - Should return empty results, not throw exceptions - symbols.Should().BeEmpty(); - callChain.Should().BeEmpty(); - files.Should().BeEmpty(); + Assert.That(symbols, Is.Empty); + Assert.That(callChain, Is.Empty); + Assert.That(files, Is.Empty); } [Test] @@ -534,15 +533,15 @@ public async Task ProjectContextManager_TracksMultipleFiles() var context = _projectManager.GetProjectContext(); // Assert - context.Should().NotBeNull(); - context!.RootPath.Should().Be(_testProjectPath); - context.FileCount.Should().BeGreaterThan(0); - context.KnownFiles.Should().NotBeEmpty(); - context.OpenedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(5)); + Assert.That(context, Is.Not.Null); + Assert.That(context!.RootPath, Is.EqualTo(_testProjectPath)); + Assert.That(context.FileCount, Is.GreaterThan(0)); + Assert.That(context.KnownFiles, Is.Not.Empty); + Assert.That(context.OpenedAt, Is.EqualTo(DateTime.UtcNow).Within(TimeSpan.FromSeconds(5))); // Verify files we created exist in the context - context.KnownFiles.Any(f => f.Contains("Test.cs")).Should().BeTrue(); - context.KnownFiles.Any(f => f.Contains("Program.cs")).Should().BeTrue(); + Assert.That(context.KnownFiles.Any(f => f.Contains("Test.cs")), Is.True); + Assert.That(context.KnownFiles.Any(f => f.Contains("Program.cs")), Is.True); } [Test] @@ -558,8 +557,9 @@ public async Task ResourceRegistry_HandlesContentProviderExceptions() }); // Act & Assert - var act = async () => await _resourceRegistry.ReadResourceAsync("test://error"); - await act.Should().ThrowAsync().WithMessage("Test error"); + var ex = Assert.ThrowsAsync(async () => + await _resourceRegistry.ReadResourceAsync("test://error")); + Assert.That(ex!.Message, Is.EqualTo("Test error")); } [Test] @@ -586,6 +586,6 @@ public async Task Database_SupportsTransactionalOperations() var count = await _database.FindSymbolsByNameAsync("Method"); // Assert - count.Should().HaveCount(100); + Assert.That(count, Has.Count.EqualTo(100)); } } diff --git a/tests/MCPsharp.Tests/MCPsharp.Tests.csproj b/tests/MCPsharp.Tests/MCPsharp.Tests.csproj index add3291..81caec6 100644 --- a/tests/MCPsharp.Tests/MCPsharp.Tests.csproj +++ b/tests/MCPsharp.Tests/MCPsharp.Tests.csproj @@ -1,7 +1,7 @@  - net9.0 + net10.0 enable enable false @@ -15,16 +15,14 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + runtime; build; native; contentfiles; analyzers; buildtransitive all - diff --git a/tests/MCPsharp.Tests/Performance/PerformanceTests.cs b/tests/MCPsharp.Tests/Performance/PerformanceTests.cs index fbdd308..ba15fa8 100644 --- a/tests/MCPsharp.Tests/Performance/PerformanceTests.cs +++ b/tests/MCPsharp.Tests/Performance/PerformanceTests.cs @@ -43,6 +43,7 @@ protected override void Setup() [TearDown] protected override void TearDown() { + _workspace?.Dispose(); base.TearDown(); } diff --git a/tests/MCPsharp.Tests/Services/AdvancedReferenceFinderServiceTests.cs b/tests/MCPsharp.Tests/Services/AdvancedReferenceFinderServiceTests.cs index 0be8d69..d856a5a 100644 --- a/tests/MCPsharp.Tests/Services/AdvancedReferenceFinderServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/AdvancedReferenceFinderServiceTests.cs @@ -2,23 +2,25 @@ using MCPsharp.Models.Roslyn; using MCPsharp.Services.Roslyn; using MCPsharp.Tests.TestFixtures; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; /// /// Integration tests for AdvancedReferenceFinderService /// -public class AdvancedReferenceFinderServiceIntegrationTests : IDisposable +[TestFixture] +public class AdvancedReferenceFinderServiceIntegrationTests { - private readonly RoslynWorkspace _workspace; - private readonly SymbolQueryService _symbolQuery; - private readonly CallerAnalysisService _callerAnalysis; - private readonly CallChainService _callChain; - private readonly TypeUsageService _typeUsage; - private readonly AdvancedReferenceFinderService _advancedReferenceFinder; + private RoslynWorkspace _workspace; + private SymbolQueryService _symbolQuery; + private CallerAnalysisService _callerAnalysis; + private CallChainService _callChain; + private TypeUsageService _typeUsage; + private AdvancedReferenceFinderService _advancedReferenceFinder; - public AdvancedReferenceFinderServiceIntegrationTests() + [SetUp] + public void SetUp() { _workspace = new RoslynWorkspace(); _symbolQuery = new SymbolQueryService(_workspace); @@ -123,19 +125,25 @@ private void HelperMethod() } } - [Fact] + [TearDown] + public void TearDown() + { + _workspace?.Dispose(); + } + + [Test] public async Task FindCallers_ShouldReturnCallerAnalysis() { // Act var result = await _advancedReferenceFinder.FindCallersAsync("Execute", "Service"); // Assert - Assert.NotNull(result); - Assert.True(result.TotalCallers >= 1); - Assert.Contains(result.Callers, c => c.CallerType.Contains("Manager")); + Assert.That(result, Is.Not.Null); + Assert.That(result.TotalCallers, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.Callers, Has.Some.Property("CallerType").Contains("Manager")); } - [Fact] + [Test] public async Task FindCallersAtLocation_ShouldFindCallersAtLocation() { // This test requires actual file locations, which is complex to set up @@ -145,43 +153,43 @@ public async Task FindCallersAtLocation_ShouldFindCallersAtLocation() // May return null for non-existent location } - [Fact] + [Test] public async Task FindCallChains_ShouldReturnCallChains() { // Act var result = await _advancedReferenceFinder.FindCallChainsAsync("Execute", "Service", CallDirection.Backward, 5); // Assert - Assert.NotNull(result); - Assert.Equal(CallDirection.Backward, result.Direction); - Assert.True(result.TotalPaths >= 0); + Assert.That(result, Is.Not.Null); + Assert.That(result.Direction, Is.EqualTo(CallDirection.Backward)); + Assert.That(result.TotalPaths, Is.GreaterThanOrEqualTo(0)); } - [Fact] + [Test] public async Task FindTypeUsages_ShouldReturnTypeUsages() { // Act var result = await _advancedReferenceFinder.FindTypeUsagesAsync("Service"); // Assert - Assert.NotNull(result); - Assert.Equal("Service", result.TypeName); - Assert.True(result.TotalUsages >= 1); + Assert.That(result, Is.Not.Null); + Assert.That(result.TypeName, Is.EqualTo("Service")); + Assert.That(result.TotalUsages, Is.GreaterThanOrEqualTo(1)); } - [Fact] + [Test] public async Task AnalyzeCallPatterns_ShouldReturnPatternAnalysis() { // Act var result = await _advancedReferenceFinder.AnalyzeCallPatternsAsync("Execute", "Service"); // Assert - Assert.NotNull(result); - Assert.Equal("Execute", result.TargetMethod.Name); - Assert.True(result.TotalCallSites >= 1); + Assert.That(result, Is.Not.Null); + Assert.That(result.TargetMethod.Name, Is.EqualTo("Execute")); + Assert.That(result.TotalCallSites, Is.GreaterThanOrEqualTo(1)); } - [Fact] + [Test] public async Task FindCallChainsBetween_ShouldFindPaths() { // Arrange @@ -205,77 +213,77 @@ public async Task FindCallChainsBetween_ShouldFindPaths() var result = await _advancedReferenceFinder.FindCallChainsBetweenAsync(fromMethod, toMethod, 10); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); // May return empty in our simple test setup } - [Fact] + [Test] public async Task FindRecursiveCallChains_ShouldDetectRecursion() { // Act var result = await _advancedReferenceFinder.FindRecursiveCallChainsAsync("RecursiveMethod", "RecursiveService", 10); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); // Should detect recursive calls if they exist } - [Fact] + [Test] public async Task AnalyzeInheritance_ShouldAnalyzeInheritance() { // Act var result = await _advancedReferenceFinder.AnalyzeInheritanceAsync("Service"); // Assert - Assert.NotNull(result); - Assert.Equal("Service", result.TargetType); + Assert.That(result, Is.Not.Null); + Assert.That(result.TargetType, Is.EqualTo("Service")); } - [Fact] + [Test] public async Task FindUnusedMethods_ShouldFindUnusedMethods() { // Act var result = await _advancedReferenceFinder.FindUnusedMethodsAsync("MCPsharp.Tests.TestFixtures"); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); // May find unused methods depending on the test setup } - [Fact] + [Test] public async Task FindTestOnlyMethods_ShouldFindTestOnlyMethods() { // Act var result = await _advancedReferenceFinder.FindTestOnlyMethods(); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); // May return empty since our test files aren't actual test files } - [Fact] + [Test] public async Task AnalyzeCallGraph_ShouldAnalyzeCallGraph() { // Act var result = await _advancedReferenceFinder.AnalyzeCallGraphAsync("Service", null); // Assert - Assert.NotNull(result); - Assert.True(result.Methods.Count >= 1); + Assert.That(result, Is.Not.Null); + Assert.That(result.Methods.Count, Is.GreaterThanOrEqualTo(1)); } - [Fact] + [Test] public async Task FindCircularDependencies_ShouldDetectCycles() { // Act var result = await _advancedReferenceFinder.FindCircularDependenciesAsync("MCPsharp.Tests.TestFixtures"); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); // Should detect the indirect recursive cycle in RecursiveService } - [Fact] + [Test] public async Task FindShortestPath_ShouldReturnShortestPath() { // Arrange @@ -302,79 +310,79 @@ public async Task FindShortestPath_ShouldReturnShortestPath() // May return null if no path exists } - [Fact] + [Test] public async Task FindReachableMethods_ShouldFindReachableMethods() { // Act var result = await _advancedReferenceFinder.FindReachableMethodsAsync("Run", "Manager", 10); // Assert - Assert.NotNull(result); - Assert.Equal("Run", result.StartMethod.Name); - Assert.True(result.ReachableMethods.Count >= 1); + Assert.That(result, Is.Not.Null); + Assert.That(result.StartMethod.Name, Is.EqualTo("Run")); + Assert.That(result.ReachableMethods.Count, Is.GreaterThanOrEqualTo(1)); } - [Fact] + [Test] public async Task AnalyzeTypeDependencies_ShouldAnalyzeDependencies() { // Act var result = await _advancedReferenceFinder.AnalyzeTypeDependenciesAsync("Manager"); // Assert - Assert.NotNull(result); - Assert.Equal("Manager", result.TargetType); + Assert.That(result, Is.Not.Null); + Assert.That(result.TargetType, Is.EqualTo("Manager")); } - [Fact] + [Test] public async Task AnalyzeUsagePatterns_ShouldAnalyzePatterns() { // Act var result = await _advancedReferenceFinder.AnalyzeUsagePatternsAsync("MCPsharp.Tests.TestFixtures"); // Assert - Assert.NotNull(result); - Assert.True(result.TypeStatistics.Count >= 1); + Assert.That(result, Is.Not.Null); + Assert.That(result.TypeStatistics.Count, Is.GreaterThanOrEqualTo(1)); } - [Fact] + [Test] public async Task FindRefactoringOpportunities_ShouldFindOpportunities() { // Act var result = await _advancedReferenceFinder.FindRefactoringOpportunitiesAsync("MCPsharp.Tests.TestFixtures"); // Assert - Assert.NotNull(result); - Assert.True(result.TotalOpportunities >= 0); + Assert.That(result, Is.Not.Null); + Assert.That(result.TotalOpportunities, Is.GreaterThanOrEqualTo(0)); } - [Fact] + [Test] public async Task AnalyzeMethodComprehensively_ShouldReturnComprehensiveAnalysis() { // Act var result = await _advancedReferenceFinder.AnalyzeMethodComprehensivelyAsync("Execute", "Service"); // Assert - Assert.NotNull(result); - Assert.Equal("Execute", result.MethodName); - Assert.Equal("Service", result.ContainingType); - Assert.NotNull(result.Callers); - Assert.NotNull(result.CallPatterns); + Assert.That(result, Is.Not.Null); + Assert.That(result.MethodName, Is.EqualTo("Execute")); + Assert.That(result.ContainingType, Is.EqualTo("Service")); + Assert.That(result.Callers, Is.Not.Null); + Assert.That(result.CallPatterns, Is.Not.Null); } - [Fact] + [Test] public async Task AnalyzeTypeComprehensively_ShouldReturnComprehensiveAnalysis() { // Act var result = await _advancedReferenceFinder.AnalyzeTypeComprehensivelyAsync("Service"); // Assert - Assert.NotNull(result); - Assert.Equal("Service", result.TypeName); - Assert.NotNull(result.TypeUsages); - Assert.NotNull(result.InheritanceAnalysis); + Assert.That(result, Is.Not.Null); + Assert.That(result.TypeName, Is.EqualTo("Service")); + Assert.That(result.TypeUsages, Is.Not.Null); + Assert.That(result.InheritanceAnalysis, Is.Not.Null); } - [Fact] + [Test] public async Task FindMethodsBySignature_ShouldFindMatchingMethods() { // Arrange @@ -391,38 +399,38 @@ public async Task FindMethodsBySignature_ShouldFindMatchingMethods() var result = await _advancedReferenceFinder.FindMethodsBySignatureAsync(signature); // Assert - Assert.NotNull(result); - Assert.True(result.Count >= 1); - Assert.Contains(result, m => m.Name == "Execute"); + Assert.That(result, Is.Not.Null); + Assert.That(result.Count, Is.GreaterThanOrEqualTo(1)); + Assert.That(result, Has.Some.Property("Name").EqualTo("Execute")); } - [Fact] + [Test] public async Task FindSimilarMethods_ShouldFindSimilarMethods() { // Act var result = await _advancedReferenceFinder.FindSimilarMethods("Execute", 0.7); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); // Should find methods with similar names } - [Fact] + [Test] public async Task GetCapabilities_ShouldReturnCapabilities() { // Act var result = await _advancedReferenceFinder.GetCapabilitiesAsync(); // Assert - Assert.NotNull(result); - Assert.True(result.IsWorkspaceReady); - Assert.True(result.TotalFiles >= 1); - Assert.True(result.TotalTypes >= 1); - Assert.True(result.TotalMethods >= 1); - Assert.True(result.SupportedAnalyses.Count >= 8); + Assert.That(result, Is.Not.Null); + Assert.That(result.IsWorkspaceReady, Is.True); + Assert.That(result.TotalFiles, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.TotalTypes, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.TotalMethods, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.SupportedAnalyses.Count, Is.GreaterThanOrEqualTo(8)); } - [Fact] + [Test] public void MethodComprehensiveAnalysis_ShouldCalculateCorrectProperties() { // Arrange @@ -484,13 +492,13 @@ public void MethodComprehensiveAnalysis_ShouldCalculateCorrectProperties() }; // Assert - Assert.Equal("Execute", analysis.MethodName); - Assert.Equal("Service", analysis.ContainingType); - Assert.Equal(1, analysis.TotalDirectCallers); - Assert.False(analysis.HasRecursiveCalls); + Assert.That(analysis.MethodName, Is.EqualTo("Execute")); + Assert.That(analysis.ContainingType, Is.EqualTo("Service")); + Assert.That(analysis.TotalDirectCallers, Is.EqualTo(1)); + Assert.That(analysis.HasRecursiveCalls, Is.False); } - [Fact] + [Test] public void TypeComprehensiveAnalysis_ShouldCalculateCorrectProperties() { // Arrange @@ -582,14 +590,10 @@ public void TypeComprehensiveAnalysis_ShouldCalculateCorrectProperties() }; // Assert - Assert.Equal("Service", analysis.TypeName); - Assert.Equal(5, analysis.TotalUsages); - Assert.Equal(1, analysis.InstantiationCount); - Assert.Equal(1, analysis.InterfaceImplementationCount); + Assert.That(analysis.TypeName, Is.EqualTo("Service")); + Assert.That(analysis.TotalUsages, Is.EqualTo(5)); + Assert.That(analysis.InstantiationCount, Is.EqualTo(1)); + Assert.That(analysis.InterfaceImplementationCount, Is.EqualTo(1)); } - public void Dispose() - { - // RoslynWorkspace no longer implements IDisposable - } } \ No newline at end of file diff --git a/tests/MCPsharp.Tests/Services/Analyzers/AnalyzerHostTests.cs b/tests/MCPsharp.Tests/Services/Analyzers/AnalyzerHostTests.cs index af455f0..023cdba 100644 --- a/tests/MCPsharp.Tests/Services/Analyzers/AnalyzerHostTests.cs +++ b/tests/MCPsharp.Tests/Services/Analyzers/AnalyzerHostTests.cs @@ -529,7 +529,6 @@ public void GetLoadedAnalyzers_ShouldReturnLoadedAnalyzers() var result = _analyzerHost.GetLoadedAnalyzers(); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(2)); Assert.That(result.Any(ai => ai.Id == "analyzer-1"), Is.True); Assert.That(result.Any(ai => ai.Id == "analyzer-2"), Is.True); @@ -550,7 +549,6 @@ public async Task GetHealthStatusAsync_ShouldReturnHealthStatus() var result = await _analyzerHost.GetHealthStatusAsync(); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.GreaterThanOrEqualTo(0)); } @@ -567,7 +565,7 @@ public void GetAnalyzer_WithValidId_ShouldReturnAnalyzer() var result = _analyzerHost.GetAnalyzer(analyzerId); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); if (result == null) throw new InvalidOperationException("Result should not be null"); Assert.That(result.Id, Is.EqualTo(analyzerId)); @@ -656,6 +654,14 @@ public async Task RunAnalyzerAsync_WithSameInput_ShouldProduceConsistentResults( Assert.That(result1.Findings.Count, Is.EqualTo(result2.Findings.Count)); } + [TearDown] + protected override void TearDown() + { + _mockSandbox?.Dispose(); + _mockLoggerFactory?.Dispose(); + base.TearDown(); + } + private IAnalyzer CreateMockAnalyzer(string id, string name, string version) { var analyzer = Substitute.For(); diff --git a/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/AsyncAwaitPatternIntegrationTests.cs b/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/AsyncAwaitPatternIntegrationTests.cs index a204d35..dc39582 100644 --- a/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/AsyncAwaitPatternIntegrationTests.cs +++ b/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/AsyncAwaitPatternIntegrationTests.cs @@ -1,4 +1,4 @@ -using Xunit; +using NUnit.Framework; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using MCPsharp.Services.Analyzers.BuiltIn.CodeFixes; @@ -13,37 +13,38 @@ namespace MCPsharp.Tests.Services.Analyzers.BuiltIn.CodeFixes; /// public class AsyncAwaitPatternIntegrationTests { - private readonly ILoggerFactory _loggerFactory; + private ILoggerFactory _loggerFactory = null!; - public AsyncAwaitPatternIntegrationTests() + [SetUp] + public void SetUp() { _loggerFactory = NullLoggerFactory.Instance; } - [Fact] + [Test] public void Analyzer_CanBeCreated() { // Arrange & Act var analyzer = new AsyncAwaitPatternAnalyzer(); // Assert - Assert.NotNull(analyzer); - Assert.Equal("MCP001", AsyncAwaitPatternAnalyzer.DiagnosticId); - Assert.Single(analyzer.SupportedDiagnostics); + Assert.That(analyzer, Is.Not.Null); + Assert.That(AsyncAwaitPatternAnalyzer.DiagnosticId, Is.EqualTo("MCP001")); + Assert.That(analyzer.SupportedDiagnostics, Has.Length.EqualTo(1)); } - [Fact] + [Test] public void Fixer_CanBeCreated() { // Arrange & Act var fixer = new AsyncAwaitPatternFixer(); // Assert - Assert.NotNull(fixer); - Assert.Contains(AsyncAwaitPatternAnalyzer.DiagnosticId, fixer.FixableDiagnosticIds); + Assert.That(fixer, Is.Not.Null); + Assert.That(fixer.FixableDiagnosticIds, Does.Contain(AsyncAwaitPatternAnalyzer.DiagnosticId)); } - [Fact] + [Test] public void Provider_CanBeCreated() { // Arrange @@ -53,15 +54,15 @@ public void Provider_CanBeCreated() var provider = new AsyncAwaitPatternProvider(logger); // Assert - Assert.NotNull(provider); - Assert.Equal("AsyncAwaitPattern", provider.Id); - Assert.Equal(FixProfile.Balanced, provider.Profile); - Assert.True(provider.IsFullyAutomated); - Assert.NotNull(provider.GetAnalyzer()); - Assert.NotNull(provider.GetCodeFixProvider()); + Assert.That(provider, Is.Not.Null); + Assert.That(provider.Id, Is.EqualTo("AsyncAwaitPattern")); + Assert.That(provider.Profile, Is.EqualTo(FixProfile.Balanced)); + Assert.That(provider.IsFullyAutomated, Is.True); + Assert.That(provider.GetAnalyzer(), Is.Not.Null); + Assert.That(provider.GetCodeFixProvider(), Is.Not.Null); } - [Fact] + [Test] public void Registry_CanBeCreated() { // Arrange @@ -71,14 +72,14 @@ public void Registry_CanBeCreated() var registry = new BuiltInCodeFixRegistry(logger, _loggerFactory); // Assert - Assert.NotNull(registry); + Assert.That(registry, Is.Not.Null); var providers = registry.GetAllProviders(); - Assert.NotEmpty(providers); - Assert.Contains(providers, p => p.Id == "AsyncAwaitPattern"); + Assert.That(providers, Is.Not.Empty); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "AsyncAwaitPattern"))); } - [Fact] + [Test] public void Registry_GetProviderById_ReturnsCorrectProvider() { // Arrange @@ -89,11 +90,11 @@ public void Registry_GetProviderById_ReturnsCorrectProvider() var provider = registry.GetProvider("AsyncAwaitPattern"); // Assert - Assert.NotNull(provider); - Assert.Equal("AsyncAwaitPattern", provider!.Id); + Assert.That(provider, Is.Not.Null); + Assert.That(provider!.Id, Is.EqualTo("AsyncAwaitPattern")); } - [Fact] + [Test] public void Registry_GetProvidersByProfile_ReturnsBalancedProviders() { // Arrange @@ -104,11 +105,11 @@ public void Registry_GetProvidersByProfile_ReturnsBalancedProviders() var providers = registry.GetProvidersByProfile(FixProfile.Balanced); // Assert - Assert.NotEmpty(providers); - Assert.Contains(providers, p => p.Id == "AsyncAwaitPattern"); + Assert.That(providers, Is.Not.Empty); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "AsyncAwaitPattern"))); } - [Fact] + [Test] public void Registry_GetFullyAutomatedProviders_IncludesAsyncAwait() { // Arrange @@ -119,11 +120,11 @@ public void Registry_GetFullyAutomatedProviders_IncludesAsyncAwait() var providers = registry.GetFullyAutomatedProviders(); // Assert - Assert.NotEmpty(providers); - Assert.Contains(providers, p => p.Id == "AsyncAwaitPattern"); + Assert.That(providers, Is.Not.Empty); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "AsyncAwaitPattern"))); } - [Fact] + [Test] public void Registry_GetStatistics_ReturnsCorrectStats() { // Arrange @@ -134,63 +135,63 @@ public void Registry_GetStatistics_ReturnsCorrectStats() var stats = registry.GetStatistics(); // Assert - Assert.True(stats.TotalProviders >= 1); - Assert.True(stats.FullyAutomatedCount >= 1); - Assert.True(stats.TotalFixableDiagnostics >= 1); - Assert.Contains(FixProfile.Balanced, stats.ProvidersByProfile.Keys); + Assert.That(stats.TotalProviders, Is.GreaterThanOrEqualTo(1)); + Assert.That(stats.FullyAutomatedCount, Is.GreaterThanOrEqualTo(1)); + Assert.That(stats.TotalFixableDiagnostics, Is.GreaterThanOrEqualTo(1)); + Assert.That(stats.ProvidersByProfile.Keys, Does.Contain(FixProfile.Balanced)); } - [Fact] + [Test] public void FixConfiguration_DefaultValues_AreCorrect() { // Arrange & Act var config = new FixConfiguration(); // Assert - Assert.Equal(FixProfile.Balanced, config.Profile); - Assert.True(config.RequireUserApproval); - Assert.True(config.CreateBackup); - Assert.True(config.ValidateAfterApply); - Assert.False(config.StopOnFirstError); + Assert.That(config.Profile, Is.EqualTo(FixProfile.Balanced)); + Assert.That(config.RequireUserApproval, Is.True); + Assert.That(config.CreateBackup, Is.True); + Assert.That(config.ValidateAfterApply, Is.True); + Assert.That(config.StopOnFirstError, Is.False); } - [Fact] + [Test] public void FixConfiguration_ConservativeDefault_IsCorrect() { // Arrange & Act var config = FixConfiguration.ConservativeDefault; // Assert - Assert.Equal(FixProfile.Conservative, config.Profile); - Assert.False(config.RequireUserApproval); // Conservative is safe enough for auto-apply - Assert.True(config.CreateBackup); - Assert.True(config.ValidateAfterApply); + Assert.That(config.Profile, Is.EqualTo(FixProfile.Conservative)); + Assert.That(config.RequireUserApproval, Is.False); // Conservative is safe enough for auto-apply + Assert.That(config.CreateBackup, Is.True); + Assert.That(config.ValidateAfterApply, Is.True); } - [Fact] + [Test] public void FixConfiguration_BalancedDefault_IsCorrect() { // Arrange & Act var config = FixConfiguration.BalancedDefault; // Assert - Assert.Equal(FixProfile.Balanced, config.Profile); - Assert.True(config.RequireUserApproval); - Assert.True(config.CreateBackup); - Assert.True(config.ValidateAfterApply); + Assert.That(config.Profile, Is.EqualTo(FixProfile.Balanced)); + Assert.That(config.RequireUserApproval, Is.True); + Assert.That(config.CreateBackup, Is.True); + Assert.That(config.ValidateAfterApply, Is.True); } - [Fact] + [Test] public void FixConfiguration_AggressiveDefault_IsCorrect() { // Arrange & Act var config = FixConfiguration.AggressiveDefault; // Assert - Assert.Equal(FixProfile.Aggressive, config.Profile); - Assert.True(config.RequireUserApproval); - Assert.True(config.CreateBackup); - Assert.True(config.ValidateAfterApply); - Assert.False(config.StopOnFirstError); + Assert.That(config.Profile, Is.EqualTo(FixProfile.Aggressive)); + Assert.That(config.RequireUserApproval, Is.True); + Assert.That(config.CreateBackup, Is.True); + Assert.That(config.ValidateAfterApply, Is.True); + Assert.That(config.StopOnFirstError, Is.False); } } diff --git a/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/ExceptionLoggingIntegrationTests.cs b/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/ExceptionLoggingIntegrationTests.cs index 10b04eb..1303307 100644 --- a/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/ExceptionLoggingIntegrationTests.cs +++ b/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/ExceptionLoggingIntegrationTests.cs @@ -1,4 +1,4 @@ -using Xunit; +using NUnit.Framework; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using MCPsharp.Services.Analyzers.BuiltIn.CodeFixes; @@ -13,26 +13,27 @@ namespace MCPsharp.Tests.Services.Analyzers.BuiltIn.CodeFixes; /// public class ExceptionLoggingIntegrationTests { - private readonly ILoggerFactory _loggerFactory; + private ILoggerFactory _loggerFactory = null!; - public ExceptionLoggingIntegrationTests() + [SetUp] + public void SetUp() { _loggerFactory = NullLoggerFactory.Instance; } - [Fact] + [Test] public void Analyzer_CanBeCreated() { // Arrange & Act var analyzer = new ExceptionLoggingAnalyzer(); // Assert - Assert.NotNull(analyzer); - Assert.Equal("MCP002", ExceptionLoggingAnalyzer.DiagnosticId); - Assert.Single(analyzer.SupportedDiagnostics); + Assert.That(analyzer, Is.Not.Null); + Assert.That(ExceptionLoggingAnalyzer.DiagnosticId, Is.EqualTo("MCP002")); + Assert.That(analyzer.SupportedDiagnostics, Has.Length.EqualTo(1)); } - [Fact] + [Test] public void Analyzer_DiagnosticDescriptor_HasCorrectProperties() { // Arrange @@ -42,23 +43,23 @@ public void Analyzer_DiagnosticDescriptor_HasCorrectProperties() var descriptor = analyzer.SupportedDiagnostics[0]; // Assert - Assert.Equal("MCP002", descriptor.Id); - Assert.Equal("Logging", descriptor.Category); - Assert.True(descriptor.IsEnabledByDefault); + Assert.That(descriptor.Id, Is.EqualTo("MCP002")); + Assert.That(descriptor.Category, Is.EqualTo("Logging")); + Assert.That(descriptor.IsEnabledByDefault, Is.True); } - [Fact] + [Test] public void Fixer_CanBeCreated() { // Arrange & Act var fixer = new ExceptionLoggingFixer(); // Assert - Assert.NotNull(fixer); - Assert.Contains(ExceptionLoggingAnalyzer.DiagnosticId, fixer.FixableDiagnosticIds); + Assert.That(fixer, Is.Not.Null); + Assert.That(fixer.FixableDiagnosticIds, Does.Contain(ExceptionLoggingAnalyzer.DiagnosticId)); } - [Fact] + [Test] public void Fixer_FixableDiagnosticIds_ContainsMCP002() { // Arrange @@ -68,11 +69,11 @@ public void Fixer_FixableDiagnosticIds_ContainsMCP002() var ids = fixer.FixableDiagnosticIds; // Assert - Assert.Single(ids); - Assert.Equal("MCP002", ids[0]); + Assert.That(ids, Has.Length.EqualTo(1)); + Assert.That(ids[0], Is.EqualTo("MCP002")); } - [Fact] + [Test] public void Provider_CanBeCreated() { // Arrange @@ -82,15 +83,15 @@ public void Provider_CanBeCreated() var provider = new ExceptionLoggingProvider(logger); // Assert - Assert.NotNull(provider); - Assert.Equal("ExceptionLogging", provider.Id); - Assert.Equal(FixProfile.Balanced, provider.Profile); - Assert.True(provider.IsFullyAutomated); - Assert.NotNull(provider.GetAnalyzer()); - Assert.NotNull(provider.GetCodeFixProvider()); + Assert.That(provider, Is.Not.Null); + Assert.That(provider.Id, Is.EqualTo("ExceptionLogging")); + Assert.That(provider.Profile, Is.EqualTo(FixProfile.Balanced)); + Assert.That(provider.IsFullyAutomated, Is.True); + Assert.That(provider.GetAnalyzer(), Is.Not.Null); + Assert.That(provider.GetCodeFixProvider(), Is.Not.Null); } - [Fact] + [Test] public void Provider_Properties_AreCorrect() { // Arrange @@ -98,14 +99,14 @@ public void Provider_Properties_AreCorrect() var provider = new ExceptionLoggingProvider(logger); // Assert - Assert.Equal("ExceptionLogging", provider.Id); - Assert.Equal("Exception Logging Fixer", provider.Name); - Assert.Contains("exception", provider.Description.ToLowerInvariant()); - Assert.Equal(FixProfile.Balanced, provider.Profile); - Assert.True(provider.IsFullyAutomated); + Assert.That(provider.Id, Is.EqualTo("ExceptionLogging")); + Assert.That(provider.Name, Is.EqualTo("Exception Logging Fixer")); + Assert.That(provider.Description.ToLowerInvariant(), Does.Contain("exception")); + Assert.That(provider.Profile, Is.EqualTo(FixProfile.Balanced)); + Assert.That(provider.IsFullyAutomated, Is.True); } - [Fact] + [Test] public void Provider_FixableDiagnosticIds_ContainsMCP002() { // Arrange @@ -116,11 +117,11 @@ public void Provider_FixableDiagnosticIds_ContainsMCP002() var ids = provider.FixableDiagnosticIds; // Assert - Assert.Single(ids); - Assert.Equal("MCP002", ids[0]); + Assert.That(ids, Has.Length.EqualTo(1)); + Assert.That(ids[0], Is.EqualTo("MCP002")); } - [Fact] + [Test] public void Provider_GetAnalyzer_ReturnsExceptionLoggingAnalyzer() { // Arrange @@ -131,11 +132,11 @@ public void Provider_GetAnalyzer_ReturnsExceptionLoggingAnalyzer() var analyzer = provider.GetAnalyzer(); // Assert - Assert.NotNull(analyzer); - Assert.IsType(analyzer); + Assert.That(analyzer, Is.Not.Null); + Assert.That(analyzer, Is.TypeOf()); } - [Fact] + [Test] public void Provider_GetCodeFixProvider_ReturnsExceptionLoggingFixer() { // Arrange @@ -146,11 +147,11 @@ public void Provider_GetCodeFixProvider_ReturnsExceptionLoggingFixer() var fixer = provider.GetCodeFixProvider(); // Assert - Assert.NotNull(fixer); - Assert.IsType(fixer); + Assert.That(fixer, Is.Not.Null); + Assert.That(fixer, Is.TypeOf()); } - [Fact] + [Test] public void Registry_RegistersExceptionLoggingProvider() { // Arrange @@ -161,10 +162,10 @@ public void Registry_RegistersExceptionLoggingProvider() // Assert var providers = registry.GetAllProviders(); - Assert.Contains(providers, p => p.Id == "ExceptionLogging"); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "ExceptionLogging"))); } - [Fact] + [Test] public void Registry_GetProviderById_ReturnsExceptionLoggingProvider() { // Arrange @@ -175,12 +176,12 @@ public void Registry_GetProviderById_ReturnsExceptionLoggingProvider() var provider = registry.GetProvider("ExceptionLogging"); // Assert - Assert.NotNull(provider); - Assert.Equal("ExceptionLogging", provider!.Id); - Assert.IsType(provider); + Assert.That(provider, Is.Not.Null); + Assert.That(provider!.Id, Is.EqualTo("ExceptionLogging")); + Assert.That(provider, Is.TypeOf()); } - [Fact] + [Test] public void Registry_GetProvidersByProfile_IncludesExceptionLogging() { // Arrange @@ -191,11 +192,11 @@ public void Registry_GetProvidersByProfile_IncludesExceptionLogging() var providers = registry.GetProvidersByProfile(FixProfile.Balanced); // Assert - Assert.NotEmpty(providers); - Assert.Contains(providers, p => p.Id == "ExceptionLogging"); + Assert.That(providers, Is.Not.Empty); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "ExceptionLogging"))); } - [Fact] + [Test] public void Registry_GetFullyAutomatedProviders_IncludesExceptionLogging() { // Arrange @@ -206,11 +207,11 @@ public void Registry_GetFullyAutomatedProviders_IncludesExceptionLogging() var providers = registry.GetFullyAutomatedProviders(); // Assert - Assert.NotEmpty(providers); - Assert.Contains(providers, p => p.Id == "ExceptionLogging"); + Assert.That(providers, Is.Not.Empty); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "ExceptionLogging"))); } - [Fact] + [Test] public void Registry_GetProvidersForDiagnostic_ReturnsMCP002() { // Arrange @@ -221,11 +222,11 @@ public void Registry_GetProvidersForDiagnostic_ReturnsMCP002() var providers = registry.GetProvidersForDiagnostic("MCP002"); // Assert - Assert.Single(providers); - Assert.Equal("ExceptionLogging", providers[0].Id); + Assert.That(providers, Has.Length.EqualTo(1)); + Assert.That(providers[0].Id, Is.EqualTo("ExceptionLogging")); } - [Fact] + [Test] public void Registry_Statistics_IncludesExceptionLoggingProvider() { // Arrange @@ -236,8 +237,8 @@ public void Registry_Statistics_IncludesExceptionLoggingProvider() var stats = registry.GetStatistics(); // Assert - Assert.True(stats.TotalProviders >= 2); // At least AsyncAwait and ExceptionLogging - Assert.True(stats.FullyAutomatedCount >= 2); - Assert.Contains(FixProfile.Balanced, stats.ProvidersByProfile.Keys); + Assert.That(stats.TotalProviders, Is.GreaterThanOrEqualTo(2)); // At least AsyncAwait and ExceptionLogging + Assert.That(stats.FullyAutomatedCount, Is.GreaterThanOrEqualTo(2)); + Assert.That(stats.ProvidersByProfile.Keys, Does.Contain(FixProfile.Balanced)); } } diff --git a/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/StaticMethodIntegrationTests.cs b/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/StaticMethodIntegrationTests.cs index 6ffe17f..142db91 100644 --- a/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/StaticMethodIntegrationTests.cs +++ b/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/StaticMethodIntegrationTests.cs @@ -1,4 +1,4 @@ -using Xunit; +using NUnit.Framework; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using MCPsharp.Services.Analyzers.BuiltIn.CodeFixes; @@ -13,26 +13,27 @@ namespace MCPsharp.Tests.Services.Analyzers.BuiltIn.CodeFixes; /// public class StaticMethodIntegrationTests { - private readonly ILoggerFactory _loggerFactory; + private ILoggerFactory _loggerFactory = null!; - public StaticMethodIntegrationTests() + [SetUp] + public void SetUp() { _loggerFactory = NullLoggerFactory.Instance; } - [Fact] + [Test] public void Analyzer_CanBeCreated() { // Arrange & Act var analyzer = new StaticMethodAnalyzer(); // Assert - Assert.NotNull(analyzer); - Assert.Equal("MCP005", StaticMethodAnalyzer.DiagnosticId); - Assert.Single(analyzer.SupportedDiagnostics); + Assert.That(analyzer, Is.Not.Null); + Assert.That(StaticMethodAnalyzer.DiagnosticId, Is.EqualTo("MCP005")); + Assert.That(analyzer.SupportedDiagnostics, Has.Length.EqualTo(1)); } - [Fact] + [Test] public void Analyzer_DiagnosticDescriptor_HasCorrectProperties() { // Arrange @@ -42,23 +43,23 @@ public void Analyzer_DiagnosticDescriptor_HasCorrectProperties() var descriptor = analyzer.SupportedDiagnostics[0]; // Assert - Assert.Equal("MCP005", descriptor.Id); - Assert.Equal("Performance", descriptor.Category); - Assert.True(descriptor.IsEnabledByDefault); + Assert.That(descriptor.Id, Is.EqualTo("MCP005")); + Assert.That(descriptor.Category, Is.EqualTo("Performance")); + Assert.That(descriptor.IsEnabledByDefault, Is.True); } - [Fact] + [Test] public void Fixer_CanBeCreated() { // Arrange & Act var fixer = new StaticMethodFixer(); // Assert - Assert.NotNull(fixer); - Assert.Contains(StaticMethodAnalyzer.DiagnosticId, fixer.FixableDiagnosticIds); + Assert.That(fixer, Is.Not.Null); + Assert.That(fixer.FixableDiagnosticIds, Does.Contain(StaticMethodAnalyzer.DiagnosticId)); } - [Fact] + [Test] public void Fixer_FixableDiagnosticIds_ContainsMCP005() { // Arrange @@ -68,11 +69,11 @@ public void Fixer_FixableDiagnosticIds_ContainsMCP005() var ids = fixer.FixableDiagnosticIds; // Assert - Assert.Single(ids); - Assert.Equal("MCP005", ids[0]); + Assert.That(ids, Has.Length.EqualTo(1)); + Assert.That(ids[0], Is.EqualTo("MCP005")); } - [Fact] + [Test] public void Provider_CanBeCreated() { // Arrange @@ -82,15 +83,15 @@ public void Provider_CanBeCreated() var provider = new StaticMethodProvider(logger); // Assert - Assert.NotNull(provider); - Assert.Equal("StaticMethod", provider.Id); - Assert.Equal(FixProfile.Balanced, provider.Profile); - Assert.True(provider.IsFullyAutomated); - Assert.NotNull(provider.GetAnalyzer()); - Assert.NotNull(provider.GetCodeFixProvider()); + Assert.That(provider, Is.Not.Null); + Assert.That(provider.Id, Is.EqualTo("StaticMethod")); + Assert.That(provider.Profile, Is.EqualTo(FixProfile.Balanced)); + Assert.That(provider.IsFullyAutomated, Is.True); + Assert.That(provider.GetAnalyzer(), Is.Not.Null); + Assert.That(provider.GetCodeFixProvider(), Is.Not.Null); } - [Fact] + [Test] public void Provider_Properties_AreCorrect() { // Arrange @@ -98,14 +99,14 @@ public void Provider_Properties_AreCorrect() var provider = new StaticMethodProvider(logger); // Assert - Assert.Equal("StaticMethod", provider.Id); - Assert.Equal("Static Method Converter", provider.Name); - Assert.Contains("static", provider.Description.ToLowerInvariant()); - Assert.Equal(FixProfile.Balanced, provider.Profile); - Assert.True(provider.IsFullyAutomated); + Assert.That(provider.Id, Is.EqualTo("StaticMethod")); + Assert.That(provider.Name, Is.EqualTo("Static Method Converter")); + Assert.That(provider.Description.ToLowerInvariant(), Does.Contain("static")); + Assert.That(provider.Profile, Is.EqualTo(FixProfile.Balanced)); + Assert.That(provider.IsFullyAutomated, Is.True); } - [Fact] + [Test] public void Provider_FixableDiagnosticIds_ContainsMCP005() { // Arrange @@ -116,11 +117,11 @@ public void Provider_FixableDiagnosticIds_ContainsMCP005() var ids = provider.FixableDiagnosticIds; // Assert - Assert.Single(ids); - Assert.Equal("MCP005", ids[0]); + Assert.That(ids, Has.Length.EqualTo(1)); + Assert.That(ids[0], Is.EqualTo("MCP005")); } - [Fact] + [Test] public void Provider_GetAnalyzer_ReturnsStaticMethodAnalyzer() { // Arrange @@ -131,11 +132,11 @@ public void Provider_GetAnalyzer_ReturnsStaticMethodAnalyzer() var analyzer = provider.GetAnalyzer(); // Assert - Assert.NotNull(analyzer); - Assert.IsType(analyzer); + Assert.That(analyzer, Is.Not.Null); + Assert.That(analyzer, Is.TypeOf()); } - [Fact] + [Test] public void Provider_GetCodeFixProvider_ReturnsStaticMethodFixer() { // Arrange @@ -146,11 +147,11 @@ public void Provider_GetCodeFixProvider_ReturnsStaticMethodFixer() var fixer = provider.GetCodeFixProvider(); // Assert - Assert.NotNull(fixer); - Assert.IsType(fixer); + Assert.That(fixer, Is.Not.Null); + Assert.That(fixer, Is.TypeOf()); } - [Fact] + [Test] public void Registry_RegistersStaticMethodProvider() { // Arrange @@ -161,10 +162,10 @@ public void Registry_RegistersStaticMethodProvider() // Assert var providers = registry.GetAllProviders(); - Assert.Contains(providers, p => p.Id == "StaticMethod"); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "StaticMethod"))); } - [Fact] + [Test] public void Registry_GetProviderById_ReturnsStaticMethodProvider() { // Arrange @@ -175,12 +176,12 @@ public void Registry_GetProviderById_ReturnsStaticMethodProvider() var provider = registry.GetProvider("StaticMethod"); // Assert - Assert.NotNull(provider); - Assert.Equal("StaticMethod", provider!.Id); - Assert.IsType(provider); + Assert.That(provider, Is.Not.Null); + Assert.That(provider!.Id, Is.EqualTo("StaticMethod")); + Assert.That(provider, Is.TypeOf()); } - [Fact] + [Test] public void Registry_GetProvidersByProfile_IncludesStaticMethod() { // Arrange @@ -191,11 +192,11 @@ public void Registry_GetProvidersByProfile_IncludesStaticMethod() var providers = registry.GetProvidersByProfile(FixProfile.Balanced); // Assert - Assert.NotEmpty(providers); - Assert.Contains(providers, p => p.Id == "StaticMethod"); + Assert.That(providers, Is.Not.Empty); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "StaticMethod"))); } - [Fact] + [Test] public void Registry_GetFullyAutomatedProviders_IncludesStaticMethod() { // Arrange @@ -206,11 +207,11 @@ public void Registry_GetFullyAutomatedProviders_IncludesStaticMethod() var providers = registry.GetFullyAutomatedProviders(); // Assert - Assert.NotEmpty(providers); - Assert.Contains(providers, p => p.Id == "StaticMethod"); + Assert.That(providers, Is.Not.Empty); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "StaticMethod"))); } - [Fact] + [Test] public void Registry_GetProvidersForDiagnostic_ReturnsMCP005() { // Arrange @@ -221,11 +222,11 @@ public void Registry_GetProvidersForDiagnostic_ReturnsMCP005() var providers = registry.GetProvidersForDiagnostic("MCP005"); // Assert - Assert.Single(providers); - Assert.Equal("StaticMethod", providers[0].Id); + Assert.That(providers, Has.Length.EqualTo(1)); + Assert.That(providers[0].Id, Is.EqualTo("StaticMethod")); } - [Fact] + [Test] public void Registry_Statistics_IncludesAllFourProviders() { // Arrange @@ -236,14 +237,14 @@ public void Registry_Statistics_IncludesAllFourProviders() var stats = registry.GetStatistics(); // Assert - Assert.Equal(4, stats.TotalProviders); // AsyncAwait, ExceptionLogging, UnusedCode, StaticMethod - Assert.Equal(4, stats.FullyAutomatedCount); - Assert.True(stats.TotalFixableDiagnostics >= 5); // MCP001, MCP002, MCP003, MCP004, MCP005 - Assert.Contains(FixProfile.Conservative, stats.ProvidersByProfile.Keys); - Assert.Contains(FixProfile.Balanced, stats.ProvidersByProfile.Keys); + Assert.That(stats.TotalProviders, Is.EqualTo(4)); // AsyncAwait, ExceptionLogging, UnusedCode, StaticMethod + Assert.That(stats.FullyAutomatedCount, Is.EqualTo(4)); + Assert.That(stats.TotalFixableDiagnostics, Is.GreaterThanOrEqualTo(5)); // MCP001, MCP002, MCP003, MCP004, MCP005 + Assert.That(stats.ProvidersByProfile.Keys, Does.Contain(FixProfile.Conservative)); + Assert.That(stats.ProvidersByProfile.Keys, Does.Contain(FixProfile.Balanced)); } - [Fact] + [Test] public void Registry_AllProviders_AreRegistered() { // Arrange @@ -254,14 +255,14 @@ public void Registry_AllProviders_AreRegistered() var allProviders = registry.GetAllProviders(); // Assert - Assert.Equal(4, allProviders.Length); - Assert.Contains(allProviders, p => p.Id == "AsyncAwaitPattern"); - Assert.Contains(allProviders, p => p.Id == "ExceptionLogging"); - Assert.Contains(allProviders, p => p.Id == "UnusedCode"); - Assert.Contains(allProviders, p => p.Id == "StaticMethod"); + Assert.That(allProviders.Length, Is.EqualTo(4)); + Assert.That(allProviders, Does.Contain(allProviders.First(p => p.Id == "AsyncAwaitPattern"))); + Assert.That(allProviders, Does.Contain(allProviders.First(p => p.Id == "ExceptionLogging"))); + Assert.That(allProviders, Does.Contain(allProviders.First(p => p.Id == "UnusedCode"))); + Assert.That(allProviders, Does.Contain(allProviders.First(p => p.Id == "StaticMethod"))); } - [Fact] + [Test] public void Registry_GetAnalyzers_ReturnsAllAnalyzers() { // Arrange @@ -272,14 +273,14 @@ public void Registry_GetAnalyzers_ReturnsAllAnalyzers() var analyzers = registry.GetAllAnalyzers(); // Assert - Assert.Equal(4, analyzers.Length); - Assert.Contains(analyzers, a => a is AsyncAwaitPatternAnalyzer); - Assert.Contains(analyzers, a => a is ExceptionLoggingAnalyzer); - Assert.Contains(analyzers, a => a is UnusedCodeAnalyzer); - Assert.Contains(analyzers, a => a is StaticMethodAnalyzer); + Assert.That(analyzers.Length, Is.EqualTo(4)); + Assert.That(analyzers, Does.Contain(analyzers.OfType().First())); + Assert.That(analyzers, Does.Contain(analyzers.OfType().First())); + Assert.That(analyzers, Does.Contain(analyzers.OfType().First())); + Assert.That(analyzers, Does.Contain(analyzers.OfType().First())); } - [Fact] + [Test] public void Registry_GetCodeFixProviders_ReturnsAllFixers() { // Arrange @@ -290,10 +291,10 @@ public void Registry_GetCodeFixProviders_ReturnsAllFixers() var fixers = registry.GetAllCodeFixProviders(); // Assert - Assert.Equal(4, fixers.Length); - Assert.Contains(fixers, f => f is AsyncAwaitPatternFixer); - Assert.Contains(fixers, f => f is ExceptionLoggingFixer); - Assert.Contains(fixers, f => f is UnusedCodeFixer); - Assert.Contains(fixers, f => f is StaticMethodFixer); + Assert.That(fixers.Length, Is.EqualTo(4)); + Assert.That(fixers, Does.Contain(fixers.OfType().First())); + Assert.That(fixers, Does.Contain(fixers.OfType().First())); + Assert.That(fixers, Does.Contain(fixers.OfType().First())); + Assert.That(fixers, Does.Contain(fixers.OfType().First())); } } diff --git a/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/UnusedCodeIntegrationTests.cs b/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/UnusedCodeIntegrationTests.cs index 5b70ca1..400d4fb 100644 --- a/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/UnusedCodeIntegrationTests.cs +++ b/tests/MCPsharp.Tests/Services/Analyzers/BuiltIn/CodeFixes/UnusedCodeIntegrationTests.cs @@ -1,4 +1,4 @@ -using Xunit; +using NUnit.Framework; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using MCPsharp.Services.Analyzers.BuiltIn.CodeFixes; @@ -13,27 +13,28 @@ namespace MCPsharp.Tests.Services.Analyzers.BuiltIn.CodeFixes; /// public class UnusedCodeIntegrationTests { - private readonly ILoggerFactory _loggerFactory; + private ILoggerFactory _loggerFactory = null!; - public UnusedCodeIntegrationTests() + [SetUp] + public void SetUp() { _loggerFactory = NullLoggerFactory.Instance; } - [Fact] + [Test] public void Analyzer_CanBeCreated() { // Arrange & Act var analyzer = new UnusedCodeAnalyzer(); // Assert - Assert.NotNull(analyzer); - Assert.Equal("MCP003", UnusedCodeAnalyzer.UnusedLocalDiagnosticId); - Assert.Equal("MCP004", UnusedCodeAnalyzer.UnusedFieldDiagnosticId); - Assert.Equal(2, analyzer.SupportedDiagnostics.Length); + Assert.That(analyzer, Is.Not.Null); + Assert.That(UnusedCodeAnalyzer.UnusedLocalDiagnosticId, Is.EqualTo("MCP003")); + Assert.That(UnusedCodeAnalyzer.UnusedFieldDiagnosticId, Is.EqualTo("MCP004")); + Assert.That(analyzer.SupportedDiagnostics.Length, Is.EqualTo(2)); } - [Fact] + [Test] public void Analyzer_SupportedDiagnostics_ContainsBothRules() { // Arrange @@ -43,12 +44,12 @@ public void Analyzer_SupportedDiagnostics_ContainsBothRules() var diagnostics = analyzer.SupportedDiagnostics; // Assert - Assert.Equal(2, diagnostics.Length); - Assert.Contains(diagnostics, d => d.Id == "MCP003"); - Assert.Contains(diagnostics, d => d.Id == "MCP004"); + Assert.That(diagnostics.Length, Is.EqualTo(2)); + Assert.That(diagnostics, Does.Contain(diagnostics.First(d => d.Id == "MCP003"))); + Assert.That(diagnostics, Does.Contain(diagnostics.First(d => d.Id == "MCP004"))); } - [Fact] + [Test] public void Analyzer_DiagnosticDescriptors_HaveCorrectCategories() { // Arrange @@ -58,22 +59,22 @@ public void Analyzer_DiagnosticDescriptors_HaveCorrectCategories() var diagnostics = analyzer.SupportedDiagnostics; // Assert - Assert.All(diagnostics, d => Assert.Equal("CodeQuality", d.Category)); + Assert.That(diagnostics, Has.All.Property("Category").EqualTo("CodeQuality")); } - [Fact] + [Test] public void Fixer_CanBeCreated() { // Arrange & Act var fixer = new UnusedCodeFixer(); // Assert - Assert.NotNull(fixer); - Assert.Contains(UnusedCodeAnalyzer.UnusedLocalDiagnosticId, fixer.FixableDiagnosticIds); - Assert.Contains(UnusedCodeAnalyzer.UnusedFieldDiagnosticId, fixer.FixableDiagnosticIds); + Assert.That(fixer, Is.Not.Null); + Assert.That(fixer.FixableDiagnosticIds, Does.Contain(UnusedCodeAnalyzer.UnusedLocalDiagnosticId)); + Assert.That(fixer.FixableDiagnosticIds, Does.Contain(UnusedCodeAnalyzer.UnusedFieldDiagnosticId)); } - [Fact] + [Test] public void Fixer_FixableDiagnosticIds_ContainsBothMCP003AndMCP004() { // Arrange @@ -83,12 +84,12 @@ public void Fixer_FixableDiagnosticIds_ContainsBothMCP003AndMCP004() var ids = fixer.FixableDiagnosticIds; // Assert - Assert.Equal(2, ids.Length); - Assert.Contains("MCP003", ids); - Assert.Contains("MCP004", ids); + Assert.That(ids.Length, Is.EqualTo(2)); + Assert.That(ids, Does.Contain("MCP003")); + Assert.That(ids, Does.Contain("MCP004")); } - [Fact] + [Test] public void Provider_CanBeCreated() { // Arrange @@ -98,15 +99,15 @@ public void Provider_CanBeCreated() var provider = new UnusedCodeProvider(logger); // Assert - Assert.NotNull(provider); - Assert.Equal("UnusedCode", provider.Id); - Assert.Equal(FixProfile.Conservative, provider.Profile); - Assert.True(provider.IsFullyAutomated); - Assert.NotNull(provider.GetAnalyzer()); - Assert.NotNull(provider.GetCodeFixProvider()); + Assert.That(provider, Is.Not.Null); + Assert.That(provider.Id, Is.EqualTo("UnusedCode")); + Assert.That(provider.Profile, Is.EqualTo(FixProfile.Conservative)); + Assert.That(provider.IsFullyAutomated, Is.True); + Assert.That(provider.GetAnalyzer(), Is.Not.Null); + Assert.That(provider.GetCodeFixProvider(), Is.Not.Null); } - [Fact] + [Test] public void Provider_Properties_AreCorrect() { // Arrange @@ -114,14 +115,14 @@ public void Provider_Properties_AreCorrect() var provider = new UnusedCodeProvider(logger); // Assert - Assert.Equal("UnusedCode", provider.Id); - Assert.Equal("Unused Code Remover", provider.Name); - Assert.Contains("unused", provider.Description.ToLowerInvariant()); - Assert.Equal(FixProfile.Conservative, provider.Profile); - Assert.True(provider.IsFullyAutomated); + Assert.That(provider.Id, Is.EqualTo("UnusedCode")); + Assert.That(provider.Name, Is.EqualTo("Unused Code Remover")); + Assert.That(provider.Description.ToLowerInvariant(), Does.Contain("unused")); + Assert.That(provider.Profile, Is.EqualTo(FixProfile.Conservative)); + Assert.That(provider.IsFullyAutomated, Is.True); } - [Fact] + [Test] public void Provider_FixableDiagnosticIds_ContainsBothMCP003AndMCP004() { // Arrange @@ -132,12 +133,12 @@ public void Provider_FixableDiagnosticIds_ContainsBothMCP003AndMCP004() var ids = provider.FixableDiagnosticIds; // Assert - Assert.Equal(2, ids.Length); - Assert.Contains("MCP003", ids); - Assert.Contains("MCP004", ids); + Assert.That(ids.Length, Is.EqualTo(2)); + Assert.That(ids, Does.Contain("MCP003")); + Assert.That(ids, Does.Contain("MCP004")); } - [Fact] + [Test] public void Provider_GetAnalyzer_ReturnsUnusedCodeAnalyzer() { // Arrange @@ -148,11 +149,11 @@ public void Provider_GetAnalyzer_ReturnsUnusedCodeAnalyzer() var analyzer = provider.GetAnalyzer(); // Assert - Assert.NotNull(analyzer); - Assert.IsType(analyzer); + Assert.That(analyzer, Is.Not.Null); + Assert.That(analyzer, Is.TypeOf()); } - [Fact] + [Test] public void Provider_GetCodeFixProvider_ReturnsUnusedCodeFixer() { // Arrange @@ -163,11 +164,11 @@ public void Provider_GetCodeFixProvider_ReturnsUnusedCodeFixer() var fixer = provider.GetCodeFixProvider(); // Assert - Assert.NotNull(fixer); - Assert.IsType(fixer); + Assert.That(fixer, Is.Not.Null); + Assert.That(fixer, Is.TypeOf()); } - [Fact] + [Test] public void Registry_RegistersUnusedCodeProvider() { // Arrange @@ -178,10 +179,10 @@ public void Registry_RegistersUnusedCodeProvider() // Assert var providers = registry.GetAllProviders(); - Assert.Contains(providers, p => p.Id == "UnusedCode"); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "UnusedCode"))); } - [Fact] + [Test] public void Registry_GetProviderById_ReturnsUnusedCodeProvider() { // Arrange @@ -192,12 +193,12 @@ public void Registry_GetProviderById_ReturnsUnusedCodeProvider() var provider = registry.GetProvider("UnusedCode"); // Assert - Assert.NotNull(provider); - Assert.Equal("UnusedCode", provider!.Id); - Assert.IsType(provider); + Assert.That(provider, Is.Not.Null); + Assert.That(provider!.Id, Is.EqualTo("UnusedCode")); + Assert.That(provider, Is.TypeOf()); } - [Fact] + [Test] public void Registry_GetProvidersByProfile_IncludesUnusedCodeInConservative() { // Arrange @@ -208,11 +209,11 @@ public void Registry_GetProvidersByProfile_IncludesUnusedCodeInConservative() var providers = registry.GetProvidersByProfile(FixProfile.Conservative); // Assert - Assert.NotEmpty(providers); - Assert.Contains(providers, p => p.Id == "UnusedCode"); + Assert.That(providers, Is.Not.Empty); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "UnusedCode"))); } - [Fact] + [Test] public void Registry_GetFullyAutomatedProviders_IncludesUnusedCode() { // Arrange @@ -223,11 +224,11 @@ public void Registry_GetFullyAutomatedProviders_IncludesUnusedCode() var providers = registry.GetFullyAutomatedProviders(); // Assert - Assert.NotEmpty(providers); - Assert.Contains(providers, p => p.Id == "UnusedCode"); + Assert.That(providers, Is.Not.Empty); + Assert.That(providers, Does.Contain(providers.First(p => p.Id == "UnusedCode"))); } - [Fact] + [Test] public void Registry_GetProvidersForDiagnostic_ReturnsMCP003() { // Arrange @@ -238,11 +239,11 @@ public void Registry_GetProvidersForDiagnostic_ReturnsMCP003() var providers = registry.GetProvidersForDiagnostic("MCP003"); // Assert - Assert.Single(providers); - Assert.Equal("UnusedCode", providers[0].Id); + Assert.That(providers, Has.Length.EqualTo(1)); + Assert.That(providers[0].Id, Is.EqualTo("UnusedCode")); } - [Fact] + [Test] public void Registry_GetProvidersForDiagnostic_ReturnsMCP004() { // Arrange @@ -253,11 +254,11 @@ public void Registry_GetProvidersForDiagnostic_ReturnsMCP004() var providers = registry.GetProvidersForDiagnostic("MCP004"); // Assert - Assert.Single(providers); - Assert.Equal("UnusedCode", providers[0].Id); + Assert.That(providers, Has.Length.EqualTo(1)); + Assert.That(providers[0].Id, Is.EqualTo("UnusedCode")); } - [Fact] + [Test] public void Registry_Statistics_IncludesUnusedCodeProvider() { // Arrange @@ -268,8 +269,8 @@ public void Registry_Statistics_IncludesUnusedCodeProvider() var stats = registry.GetStatistics(); // Assert - Assert.True(stats.TotalProviders >= 3); // AsyncAwait, ExceptionLogging, UnusedCode - Assert.True(stats.FullyAutomatedCount >= 3); - Assert.Contains(FixProfile.Conservative, stats.ProvidersByProfile.Keys); + Assert.That(stats.TotalProviders, Is.GreaterThanOrEqualTo(3)); // AsyncAwait, ExceptionLogging, UnusedCode + Assert.That(stats.FullyAutomatedCount, Is.GreaterThanOrEqualTo(3)); + Assert.That(stats.ProvidersByProfile.Keys, Does.Contain(FixProfile.Conservative)); } } diff --git a/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerAdapterTests.cs b/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerAdapterTests.cs index 993b37f..a5e4133 100644 --- a/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerAdapterTests.cs +++ b/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerAdapterTests.cs @@ -238,7 +238,6 @@ public async Task AnalyzeAsync_WithValidCode_ShouldReturnSuccessfulResult() Assert.That(result.Success, Is.True); Assert.That(result.FilePath, Is.EqualTo(filePath)); Assert.That(result.AnalyzerId, Is.EqualTo(adapter.Id)); - Assert.That(result.Issues, Is.Not.Null); Assert.That(result.Statistics, Is.Not.Null); Assert.That(result.Statistics["IssuesFound"], Is.GreaterThanOrEqualTo(0)); } @@ -256,7 +255,6 @@ public async Task AnalyzeAsync_WithInvalidCode_ShouldStillSucceed() var result = await adapter.AnalyzeAsync(filePath, content); // Assert - Analysis completes even with invalid syntax - Assert.That(result, Is.Not.Null); Assert.That(result.Success, Is.True); } @@ -280,7 +278,6 @@ public async Task AnalyzeAsync_WithDiagnosticProducingAnalyzer_ShouldReportIssue Assert.That(issue.RuleId, Is.EqualTo("TEST001")); Assert.That(issue.AnalyzerId, Is.EqualTo(adapter.Id)); Assert.That(issue.FilePath, Is.EqualTo(filePath)); - Assert.That(issue.Severity, Is.Not.Null); Assert.That(issue.Confidence, Is.EqualTo(Confidence.High)); } @@ -332,14 +329,11 @@ public void GetRules_ShouldReturnSupportedDiagnostics() var rules = adapter.GetRules(); // Assert - Assert.That(rules, Is.Not.Null); Assert.That(rules.Length, Is.GreaterThan(0)); var rule = rules[0]; Assert.That(rule.Id, Is.EqualTo("TEST001")); Assert.That(rule.Title, Is.Not.Empty); - Assert.That(rule.Category, Is.Not.Null); - Assert.That(rule.DefaultSeverity, Is.Not.Null); } [Test] @@ -353,7 +347,6 @@ public void GetRules_WithAnalyzerWithoutDiagnostics_ShouldReturnEmpty() var rules = adapter.GetRules(); // Assert - Assert.That(rules, Is.Not.Null); Assert.That(rules.Length, Is.EqualTo(0)); } @@ -404,7 +397,6 @@ public void GetFixes_ShouldReturnEmpty() var fixes = adapter.GetFixes("TEST001"); // Assert - Assert.That(fixes, Is.Not.Null); Assert.That(fixes.Length, Is.EqualTo(0)); } diff --git a/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerLoaderTests.cs b/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerLoaderTests.cs index c45824d..6d2e47c 100644 --- a/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerLoaderTests.cs +++ b/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerLoaderTests.cs @@ -71,7 +71,6 @@ public async Task LoadAnalyzersFromAssemblyAsync_WithNonExistentFile_ShouldRetur var result = await _loader.LoadAnalyzersFromAssemblyAsync(nonExistentPath); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(0)); } @@ -85,7 +84,6 @@ public async Task LoadAnalyzersFromAssemblyAsync_WithInvalidAssembly_ShouldRetur var result = await _loader.LoadAnalyzersFromAssemblyAsync(invalidAssembly); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(0)); } @@ -99,7 +97,6 @@ public async Task LoadAnalyzersFromAssemblyAsync_WithValidAssembly_ShouldLoadAna var result = await _loader.LoadAnalyzersFromAssemblyAsync(assemblyPath); // Assert - Assert.That(result, Is.Not.Null); // May be zero if no analyzers in test assembly, that's ok Assert.That(result.Length, Is.GreaterThanOrEqualTo(0)); } @@ -146,7 +143,8 @@ public async Task LoadAnalyzersFromAssemblyAsync_ShouldLogInformation() var result = await _loader.LoadAnalyzersFromAssemblyAsync(assemblyPath); // Assert - Just verify it completes without throwing - Assert.That(result, Is.Not.Null); + // Result is ImmutableArray, always has value + Assert.Pass(); } #endregion @@ -163,7 +161,6 @@ public async Task LoadAnalyzersFromAssembliesAsync_WithEmptyList_ShouldReturnEmp var result = await _loader.LoadAnalyzersFromAssembliesAsync(emptyList); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(0)); } @@ -179,7 +176,6 @@ public async Task LoadAnalyzersFromAssembliesAsync_WithMultipleAssemblies_Should var result = await _loader.LoadAnalyzersFromAssembliesAsync(assemblies); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.GreaterThanOrEqualTo(0)); } @@ -195,8 +191,8 @@ public async Task LoadAnalyzersFromAssembliesAsync_WithMixedValidAndInvalid_Shou var result = await _loader.LoadAnalyzersFromAssembliesAsync(assemblies); // Assert - Assert.That(result, Is.Not.Null); // Should not throw, should handle invalid gracefully + Assert.Pass(); } [Test] @@ -226,7 +222,6 @@ public void DiscoverAnalyzerAssemblies_WithNonExistentDirectory_ShouldReturnEmpt var result = _loader.DiscoverAnalyzerAssemblies(nonExistentDir); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(0)); } @@ -240,7 +235,6 @@ public void DiscoverAnalyzerAssemblies_WithEmptyDirectory_ShouldReturnEmpty() var result = _loader.DiscoverAnalyzerAssemblies(emptyDir); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(0)); } @@ -256,8 +250,8 @@ public void DiscoverAnalyzerAssemblies_WithDirectoryContainingNonAnalyzerDlls_Sh var result = _loader.DiscoverAnalyzerAssemblies(dir); // Assert - Assert.That(result, Is.Not.Null); // Should handle invalid DLLs gracefully + Assert.Pass(); } [Test] @@ -276,8 +270,8 @@ public void DiscoverAnalyzerAssemblies_WithRecursiveSearch_ShouldSearchSubdirect var result = _loader.DiscoverAnalyzerAssemblies(rootDir, recursive: true); // Assert - Assert.That(result, Is.Not.Null); // Should find assemblies in subdirectories + Assert.Pass(); } [Test] @@ -296,7 +290,6 @@ public void DiscoverAnalyzerAssemblies_WithNonRecursiveSearch_ShouldNotSearchSub var result = _loader.DiscoverAnalyzerAssemblies(rootDir, recursive: false); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(0)); // Should not find in subdirectory } @@ -339,7 +332,6 @@ public async Task LoadAnalyzersFromNuGetCacheAsync_ShouldReturnAnalyzers() var result = await _loader.LoadAnalyzersFromNuGetCacheAsync(); // Assert - Assert.That(result, Is.Not.Null); // May be empty if no NuGet cache exists, that's ok Assert.That(result.Length, Is.GreaterThanOrEqualTo(0)); } @@ -403,7 +395,6 @@ public void GetAnalyzerAssemblyInfo_WithValidAssembly_ShouldReturnInfo() Assert.That(result.AssemblyName, Is.Not.Empty); Assert.That(result.Version, Is.Not.Null); Assert.That(result.AnalyzerCount, Is.GreaterThan(0)); - Assert.That(result.AnalyzerTypeNames, Is.Not.Null); Assert.That(result.AnalyzerTypeNames.Length, Is.EqualTo(result.AnalyzerCount)); } } @@ -435,7 +426,6 @@ public async Task LoadAnalyzersFromAssemblyAsync_WithExceptionInAnalyzerConstruc var result = await _loader.LoadAnalyzersFromAssemblyAsync(assemblyPath); // Assert - Should not throw, should return empty - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(0)); } @@ -470,9 +460,16 @@ public async Task FullWorkflow_DiscoverAndLoad_ShouldComplete() var analyzers = await _loader.LoadAnalyzersFromAssembliesAsync(assemblies); // Assert - Assert.That(assemblies, Is.Not.Null); - Assert.That(analyzers, Is.Not.Null); + // Both ImmutableArrays always have values + Assert.Pass(); } #endregion + + [TearDown] + protected override void TearDown() + { + _mockLoggerFactory?.Dispose(); + base.TearDown(); + } } diff --git a/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerServiceTests.cs b/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerServiceTests.cs index 34c837f..e4a82c9 100644 --- a/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/Analyzers/RoslynAnalyzerServiceTests.cs @@ -92,7 +92,6 @@ public async Task LoadAnalyzersAsync_WithValidAssembly_ShouldLoadAndRegisterAnal var result = await _service.LoadAnalyzersAsync(assemblyPath); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(2)); Assert.That(result[0].Id, Is.EqualTo("analyzer1")); Assert.That(result[1].Id, Is.EqualTo("analyzer2")); @@ -114,7 +113,6 @@ public async Task LoadAnalyzersAsync_WithFailure_ShouldReturnEmpty() var result = await _service.LoadAnalyzersAsync(assemblyPath); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(0)); } @@ -451,7 +449,6 @@ public void GetLoadedAnalyzers_Initially_ShouldReturnEmpty() var result = _service.GetLoadedAnalyzers(); // Assert - Assert.That(result, Is.Not.Null); Assert.That(result.Length, Is.EqualTo(0)); } diff --git a/tests/MCPsharp.Tests/Services/Analyzers/StaticMethodAnalyzerTests.cs b/tests/MCPsharp.Tests/Services/Analyzers/StaticMethodAnalyzerTests.cs index 5eee123..f61b5dd 100644 --- a/tests/MCPsharp.Tests/Services/Analyzers/StaticMethodAnalyzerTests.cs +++ b/tests/MCPsharp.Tests/Services/Analyzers/StaticMethodAnalyzerTests.cs @@ -6,7 +6,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Text; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services.Analyzers; @@ -63,7 +63,7 @@ private static async Task ApplyCodeFix(Document document, Diagnostic d return newSolution.GetDocument(document.Id)!; } - [Fact] + [Test] public async Task NoDuplicateStaticModifier_WhenAppliedTwice() { // Arrange @@ -80,24 +80,24 @@ private int Add(int a, int b) // Act - Apply fix once var diagnostics = await GetDiagnostics(document, compilation); - Assert.Single(diagnostics); + Assert.That(diagnostics, Has.Count.EqualTo(1)); document = await ApplyCodeFix(document, diagnostics[0]); var text = (await document.GetTextAsync()).ToString(); // Verify first application - Assert.Contains("private static", text); - Assert.DoesNotContain("static static", text); + Assert.That(text, Does.Contain("private static")); + Assert.That(text, Does.Not.Contain("static static")); // Act - Try to apply again (shouldn't produce duplicate) compilation = await document.Project.GetCompilationAsync(); diagnostics = await GetDiagnostics(document, compilation!); // Should be no diagnostics since method is already static - Assert.Empty(diagnostics); + Assert.That(diagnostics, Is.Empty); } - [Fact] + [Test] public async Task DoesNotSuggestStatic_WhenMethodAccessesInstanceMember() { // Arrange @@ -118,10 +118,10 @@ private int GetValuePlusTen() var diagnostics = await GetDiagnostics(document, compilation); // Assert - Should not suggest making it static since it accesses _value - Assert.Empty(diagnostics); + Assert.That(diagnostics, Is.Empty); } - [Fact] + [Test] public async Task DoesNotSuggestStatic_WhenMethodUsedAsDelegate() { // Arrange @@ -148,10 +148,10 @@ private void HelperMethod() var diagnostics = await GetDiagnostics(document, compilation); // Assert - Should not suggest making HelperMethod static since it's used as a delegate - Assert.Empty(diagnostics); + Assert.That(diagnostics, Is.Empty); } - [Fact] + [Test] public async Task SuggestsStatic_WhenMethodDoesNotAccessInstanceMembers() { // Arrange @@ -170,11 +170,11 @@ private int Add(int a, int b) var diagnostics = await GetDiagnostics(document, compilation); // Assert - Assert.Single(diagnostics); - Assert.Equal(StaticMethodAnalyzer.DiagnosticId, diagnostics[0].Id); + Assert.That(diagnostics, Has.Count.EqualTo(1)); + Assert.That(diagnostics[0].Id, Is.EqualTo(StaticMethodAnalyzer.DiagnosticId)); } - [Fact] + [Test] public async Task ProperlyFormatsStaticModifier_WithMultipleModifiers() { // Arrange @@ -192,15 +192,15 @@ private async Task CalculateAsync(int a, int b) // Act var diagnostics = await GetDiagnostics(document, compilation); - Assert.Single(diagnostics); + Assert.That(diagnostics, Has.Count.EqualTo(1)); document = await ApplyCodeFix(document, diagnostics[0]); var text = (await document.GetTextAsync()).ToString(); // Assert - Should be "private static async" with proper spacing - Assert.Contains("private static async", text); - Assert.DoesNotContain("static static", text); - Assert.DoesNotContain(" static", text); // No double spaces before static - Assert.DoesNotContain("static ", text); // No double spaces after static + Assert.That(text, Does.Contain("private static async")); + Assert.That(text, Does.Not.Contain("static static")); + Assert.That(text, Does.Not.Contain(" static")); // No double spaces before static + Assert.That(text, Does.Not.Contain("static ")); // No double spaces after static } } diff --git a/tests/MCPsharp.Tests/Services/BulkEdit/BulkEditServiceTests.cs b/tests/MCPsharp.Tests/Services/BulkEdit/BulkEditServiceTests.cs index 4b6f63f..1d9a5cb 100644 --- a/tests/MCPsharp.Tests/Services/BulkEdit/BulkEditServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/BulkEdit/BulkEditServiceTests.cs @@ -94,7 +94,7 @@ public void BulkReplaceAsync_WithInvalidRegex_ShouldFail() var ex = Assert.ThrowsAsync(async () => await _service.BulkReplaceAsync(files, invalidPattern, "replacement")); - Assert.NotNull(ex); + Assert.That(ex, Is.Not.Null); if (ex == null) throw new InvalidOperationException("Exception should not be null"); Assert.That(ex.Message, Does.Contain("Invalid pattern")); @@ -113,7 +113,7 @@ public async Task BulkReplaceAsync_WithCreateBackups_ShouldCreateBackupFiles() // Assert Assert.That(result.Success, Is.True); - Assert.NotNull(result.RollbackInfo); + Assert.That(result.RollbackInfo, Is.Not.Null); if (result.RollbackInfo == null) throw new InvalidOperationException("RollbackInfo should not be null"); Assert.That(result.RollbackInfo.Files.Count, Is.EqualTo(1)); @@ -392,7 +392,7 @@ public async Task RollbackBulkEditAsync_WithValidRollbackId_ShouldRestoreFiles() var editResult = await _service.BulkReplaceAsync(new[] { testFile }, "Original", "Modified", options); var rollbackId = editResult.RollbackInfo?.RollbackId; - Assert.NotNull(rollbackId); + Assert.That(rollbackId, Is.Not.Null); if (rollbackId == null) throw new InvalidOperationException("Rollback ID should not be null"); Assert.That(editResult.Success, Is.True); diff --git a/tests/MCPsharp.Tests/Services/CallChainServiceTests.cs b/tests/MCPsharp.Tests/Services/CallChainServiceTests.cs index fee16ab..2493637 100644 --- a/tests/MCPsharp.Tests/Services/CallChainServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/CallChainServiceTests.cs @@ -2,21 +2,23 @@ using MCPsharp.Models.Roslyn; using MCPsharp.Services.Roslyn; using MCPsharp.Tests.TestFixtures; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; /// /// Unit tests for CallChainService /// -public class CallChainServiceTests : IDisposable +[TestFixture] +public class CallChainServiceTests { - private readonly RoslynWorkspace _workspace; - private readonly SymbolQueryService _symbolQuery; - private readonly CallerAnalysisService _callerAnalysis; - private readonly CallChainService _callChain; + private RoslynWorkspace _workspace; + private SymbolQueryService _symbolQuery; + private CallerAnalysisService _callerAnalysis; + private CallChainService _callChain; - public CallChainServiceTests() + [SetUp] + public void SetUp() { _workspace = new RoslynWorkspace(); _symbolQuery = new SymbolQueryService(_workspace); @@ -130,43 +132,43 @@ public class DataEntity } } - [Fact] + [Test] public async Task FindCallChains_Backward_ShouldFindCallers() { // Act var result = await _callChain.FindCallChainsAsync("ProcessData", "Service", 5); // Assert - Assert.NotNull(result); - Assert.Equal(CallDirection.Backward, result.Direction); - Assert.True(result.TotalPaths >= 1); - Assert.All(result.Paths, p => Assert.True(p.Steps.Count > 0)); + Assert.That(result, Is.Not.Null); + Assert.That(result.Direction, Is.EqualTo(CallDirection.Backward)); + Assert.That(result.TotalPaths, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.Paths, Has.All.Property("Steps").Property("Count").GreaterThan(0)); } - [Fact] + [Test] public async Task FindCallChains_Forward_ShouldFindCalledMethods() { // Act var result = await _callChain.FindForwardCallChainsAsync("ProcessData", "Service", 5); // Assert - Assert.NotNull(result); - Assert.Equal(CallDirection.Forward, result.Direction); - Assert.True(result.TotalPaths >= 1); + Assert.That(result, Is.Not.Null); + Assert.That(result.Direction, Is.EqualTo(CallDirection.Forward)); + Assert.That(result.TotalPaths, Is.GreaterThanOrEqualTo(1)); } - [Fact] + [Test] public async Task FindCallChains_WithMaxDepth_ShouldLimitDepth() { // Act var result = await _callChain.FindCallChainsAsync("ProcessData", "Service", 2); // Assert - Assert.NotNull(result); - Assert.All(result.Paths, p => Assert.True(p.Steps.Count <= 2)); + Assert.That(result, Is.Not.Null); + Assert.That(result.Paths, Has.All.Property("Steps").Property("Count").LessThanOrEqualTo(2)); } - [Fact] + [Test] public async Task FindCallChainsBetween_ShouldFindPathsBetweenMethods() { // Arrange @@ -190,11 +192,11 @@ public async Task FindCallChainsBetween_ShouldFindPathsBetweenMethods() var paths = await _callChain.FindCallChainsBetweenAsync(fromMethod, toMethod, 10); // Assert - Assert.NotNull(paths); + Assert.That(paths, Is.Not.Null); // This might return empty paths in our simple test setup } - [Fact] + [Test] public async Task FindRecursiveCallChains_ShouldDetectRecursion() { // Add a recursive method to test @@ -219,36 +221,36 @@ public void RecursiveMethod(int depth) var result = await _callChain.FindRecursiveCallChainsAsync("RecursiveMethod", "RecursiveClass", 10); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); // Should find recursive calls if they exist } - [Fact] + [Test] public async Task AnalyzeCallGraph_ShouldReturnCallGraph() { // Act var result = await _callChain.AnalyzeCallGraphAsync("Service", null); // Assert - Assert.NotNull(result); - Assert.True(result.Methods.Count >= 1); - Assert.NotNull(result.CallGraph); - Assert.NotNull(result.ReverseCallGraph); + Assert.That(result, Is.Not.Null); + Assert.That(result.Methods.Count, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.CallGraph, Is.Not.Null); + Assert.That(result.ReverseCallGraph, Is.Not.Null); } - [Fact] + [Test] public async Task AnalyzeCallGraph_ForNamespace_ShouldAnalyzeNamespace() { // Act var result = await _callChain.AnalyzeCallGraphAsync(null, "MCPsharp.Tests.TestFixtures"); // Assert - Assert.NotNull(result); - Assert.True(result.Methods.Count >= 1); - Assert.Equal("MCPsharp.Tests.TestFixtures", result.Scope); + Assert.That(result, Is.Not.Null); + Assert.That(result.Methods.Count, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.Scope, Is.EqualTo("MCPsharp.Tests.TestFixtures")); } - [Fact] + [Test] public async Task FindCircularDependencies_ShouldDetectCycles() { // Add circular dependency scenario @@ -276,24 +278,24 @@ public class B var result = await _callChain.FindCircularDependenciesAsync("MCPsharp.Tests.TestFixtures"); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); // Should detect circular dependencies if they exist } - [Fact] + [Test] public async Task FindReachableMethods_ShouldFindReachableMethods() { // Act var result = await _callChain.FindReachableMethodsAsync("HandleRequest", "Controller", 10); // Assert - Assert.NotNull(result); - Assert.Equal("HandleRequest", result.StartMethod.Name); - Assert.True(result.ReachableMethods.Count >= 1); - Assert.True(result.MethodsByDepth.Count >= 1); + Assert.That(result, Is.Not.Null); + Assert.That(result.StartMethod.Name, Is.EqualTo("HandleRequest")); + Assert.That(result.ReachableMethods.Count, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.MethodsByDepth.Count, Is.GreaterThanOrEqualTo(1)); } - [Fact] + [Test] public async Task FindShortestPath_ShouldReturnShortestPath() { // Arrange @@ -320,17 +322,17 @@ public async Task FindShortestPath_ShouldReturnShortestPath() // May return null if no path exists in our test setup } - [Fact] + [Test] public async Task FindCallChains_WithNonExistentMethod_ShouldReturnNull() { // Act var result = await _callChain.FindCallChainsAsync("NonExistentMethod"); // Assert - Assert.Null(result); + Assert.That(result, Is.Null); } - [Fact] + [Test] public void CallChainPath_ShouldCalculateCorrectProperties() { // Arrange @@ -355,13 +357,13 @@ public void CallChainPath_ShouldCalculateCorrectProperties() }; // Assert - Assert.Equal(1, path.Length); - Assert.Equal("Method1", path.StartMethod?.Name); - Assert.Equal("Method2", path.EndMethod?.Name); - Assert.False(path.IsRecursive); + Assert.That(path.Length, Is.EqualTo(1)); + Assert.That(path.StartMethod?.Name, Is.EqualTo("Method1")); + Assert.That(path.EndMethod?.Name, Is.EqualTo("Method2")); + Assert.That(path.IsRecursive, Is.False); } - [Fact] + [Test] public void CallChainPath_WithRecursiveCall_ShouldBeMarkedRecursive() { // Arrange @@ -395,10 +397,10 @@ public void CallChainPath_WithRecursiveCall_ShouldBeMarkedRecursive() }; // Assert - Assert.True(path.IsRecursive); + Assert.That(path.IsRecursive, Is.True); } - [Fact] + [Test] public void CircularDependency_ShouldGenerateCorrectDescription() { // Arrange @@ -445,13 +447,14 @@ public void CircularDependency_ShouldGenerateCorrectDescription() var description = circularDependency.GetDescription(); // Assert - Assert.Contains("Circular dependency", description); - Assert.Contains("MethodA", description); - Assert.Contains("MethodB", description); + Assert.That(description, Does.Contain("Circular dependency")); + Assert.That(description, Does.Contain("MethodA")); + Assert.That(description, Does.Contain("MethodB")); } - public void Dispose() + [TearDown] + public void TearDown() { - // RoslynWorkspace no longer implements IDisposable + _workspace?.Dispose(); } } \ No newline at end of file diff --git a/tests/MCPsharp.Tests/Services/CallerAnalysisServiceTests.cs b/tests/MCPsharp.Tests/Services/CallerAnalysisServiceTests.cs index 3a9f807..c41e51e 100644 --- a/tests/MCPsharp.Tests/Services/CallerAnalysisServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/CallerAnalysisServiceTests.cs @@ -4,7 +4,7 @@ using MCPsharp.Models.Roslyn; using MCPsharp.Services.Roslyn; using MCPsharp.Tests.TestFixtures; -using Xunit; +using NUnit.Framework; using System; using System.Collections.Generic; using System.IO; @@ -16,13 +16,15 @@ namespace MCPsharp.Tests.Services; /// /// Unit tests for CallerAnalysisService /// +[TestFixture] public class CallerAnalysisServiceTests { - private readonly RoslynWorkspace _workspace; - private readonly SymbolQueryService _symbolQuery; - private readonly CallerAnalysisService _callerAnalysis; + private RoslynWorkspace _workspace; + private SymbolQueryService _symbolQuery; + private CallerAnalysisService _callerAnalysis; - public CallerAnalysisServiceTests() + [SetUp] + public void SetUp() { _workspace = new RoslynWorkspace(); _symbolQuery = new SymbolQueryService(_workspace); @@ -130,20 +132,26 @@ public string GetData() // Cleanup of tempDir would happen in a Dispose method if we had one } - [Fact] + [TearDown] + public void TearDown() + { + _workspace?.Dispose(); + } + + [Test] public async Task FindCallers_ShouldFindDirectCallers() { // Act var result = await _callerAnalysis.FindCallersAsync("Execute", "IService"); // Assert - Assert.NotNull(result); - Assert.Equal("Execute", result.TargetSymbol); - Assert.True(result.TotalCallers >= 1); - Assert.Contains(result.Callers, c => c.CallerType.Contains("Consumer")); + Assert.That(result, Is.Not.Null); + Assert.That(result.TargetSymbol, Is.EqualTo("Execute")); + Assert.That(result.TotalCallers, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.Callers, Has.Some.Property("CallerType").Contains("Consumer")); } - [Fact] + [Test] public async Task FindCallersBySignature_ShouldFindMatchingMethods() { // Arrange @@ -160,57 +168,57 @@ public async Task FindCallersBySignature_ShouldFindMatchingMethods() var result = await _callerAnalysis.FindCallersBySignatureAsync(signature); // Assert - Assert.NotNull(result); - Assert.Equal("Execute", result.TargetSymbol); - Assert.True(result.TotalCallers >= 1); + Assert.That(result, Is.Not.Null); + Assert.That(result.TargetSymbol, Is.EqualTo("Execute")); + Assert.That(result.TotalCallers, Is.GreaterThanOrEqualTo(1)); } - [Fact] + [Test] public async Task FindDirectCallers_ShouldExcludeIndirectCalls() { // Act - Look for direct calls to implementation instead of interface var result = await _callerAnalysis.FindDirectCallersAsync("Execute", "ServiceImpl"); // Assert - Should be null since Consumer calls through interface (indirect) - Assert.Null(result); // Interface calls are classified as indirect + Assert.That(result, Is.Null); // Interface calls are classified as indirect } - [Fact] + [Test] public async Task FindIndirectCallers_ShouldIncludeInterfaceCalls() { // Act var result = await _callerAnalysis.FindIndirectCallersAsync("Execute", "IService"); // Assert - Assert.NotNull(result); - Assert.True(result.TotalCallers >= 1); - Assert.Contains(result.Callers, c => c.CallType == CallType.Indirect); + Assert.That(result, Is.Not.Null); + Assert.That(result.TotalCallers, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.Callers, Has.Some.Property("CallType").EqualTo(CallType.Indirect)); } - [Fact] + [Test] public async Task AnalyzeCallPatterns_ShouldReturnPatternAnalysis() { // Act - Look for calls to the interface method instead of implementation var result = await _callerAnalysis.AnalyzeCallPatternsAsync("Execute", "IService"); // Assert - Assert.NotNull(result); - Assert.Equal("Execute", result.TargetMethod.Name); - Assert.True(result.TotalCallSites >= 1); - Assert.NotNull(result.CallFrequencyByFile); + Assert.That(result, Is.Not.Null); + Assert.That(result.TargetMethod.Name, Is.EqualTo("Execute")); + Assert.That(result.TotalCallSites, Is.GreaterThanOrEqualTo(1)); + Assert.That(result.CallFrequencyByFile, Is.Not.Null); } - [Fact] + [Test] public async Task FindCallers_WithNonExistentMethod_ShouldReturnNull() { // Act var result = await _callerAnalysis.FindCallersAsync("NonExistentMethod"); // Assert - Assert.Null(result); + Assert.That(result, Is.Null); } - [Fact] + [Test] public async Task FindCallersAtLocation_ShouldFindCallersForSymbolAtLocation() { // This test would require more setup to get actual file locations @@ -218,10 +226,10 @@ public async Task FindCallersAtLocation_ShouldFindCallersForSymbolAtLocation() var result = await _callerAnalysis.FindCallersAtLocationAsync("TestFile.cs", 10, 5); // Should return null for non-existent file/location - Assert.Null(result); + Assert.That(result, Is.Null); } - [Fact] + [Test] public void CreateMethodSignature_ShouldCreateCorrectSignature() { // This tests a private method through reflection or by testing public behavior @@ -246,10 +254,10 @@ public void CreateMethodSignature_ShouldCreateCorrectSignature() Accessibility = "public" }); - Assert.True(matches); + Assert.That(matches, Is.True); } - [Fact] + [Test] public void MethodSignature_WithParameters_ShouldMatchCorrectly() { // Arrange @@ -280,10 +288,10 @@ public void MethodSignature_WithParameters_ShouldMatchCorrectly() }; // Act & Assert - Assert.True(signature1.Matches(signature2)); + Assert.That(signature1.Matches(signature2), Is.True); } - [Fact] + [Test] public void MethodSignature_WithDifferentParameters_ShouldNotMatch() { // Arrange @@ -312,8 +320,6 @@ public void MethodSignature_WithDifferentParameters_ShouldNotMatch() }; // Act & Assert - Assert.False(signature1.Matches(signature2)); + Assert.That(signature1.Matches(signature2), Is.False); } - - // Dispose() method removed since RoslynWorkspace no longer implements IDisposable } \ No newline at end of file diff --git a/tests/MCPsharp.Tests/Services/ConfigAnalyzerServiceTests.cs b/tests/MCPsharp.Tests/Services/ConfigAnalyzerServiceTests.cs index 1a0c687..0598e7c 100644 --- a/tests/MCPsharp.Tests/Services/ConfigAnalyzerServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/ConfigAnalyzerServiceTests.cs @@ -1,4 +1,4 @@ -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; @@ -8,11 +8,11 @@ namespace MCPsharp.Tests.Services; /// public class ConfigAnalyzerServiceTests { - [Fact] + [Test] public void Placeholder_Test() { // This is a placeholder to allow the project to compile // Phase 2 agents will implement actual tests - Assert.True(true); + Assert.That(true, Is.True); } } diff --git a/tests/MCPsharp.Tests/Services/Database/ProjectDatabaseTests.cs b/tests/MCPsharp.Tests/Services/Database/ProjectDatabaseTests.cs index 8726a5f..fa9f864 100644 --- a/tests/MCPsharp.Tests/Services/Database/ProjectDatabaseTests.cs +++ b/tests/MCPsharp.Tests/Services/Database/ProjectDatabaseTests.cs @@ -1,4 +1,3 @@ -using FluentAssertions; using MCPsharp.Models.Database; using MCPsharp.Services.Database; using NUnit.Framework; @@ -35,8 +34,8 @@ public async Task OpenInMemoryAsync_ShouldOpenDatabase() await db.OpenInMemoryAsync(); // Assert - db.IsOpen.Should().BeTrue(); - db.DatabasePath.Should().Be(":memory:"); + Assert.That(db.IsOpen, Is.True); + Assert.That(db.DatabasePath, Is.EqualTo(":memory:")); await db.DisposeAsync(); } @@ -55,9 +54,9 @@ public async Task OpenOrCreateAsync_ShouldCreateDatabaseFile() await db.OpenOrCreateAsync(tempPath); // Assert - db.IsOpen.Should().BeTrue(); - db.DatabasePath.Should().NotBeNullOrEmpty(); - File.Exists(db.DatabasePath!).Should().BeTrue(); + Assert.That(db.IsOpen, Is.True); + Assert.That(db.DatabasePath, Is.Not.Null.And.Not.Empty); + Assert.That(File.Exists(db.DatabasePath!), Is.True); await db.CloseAsync(); } @@ -80,7 +79,7 @@ public async Task CloseAsync_ShouldCloseOpenDatabase() await db.CloseAsync(); // Assert - db.IsOpen.Should().BeFalse(); + Assert.That(db.IsOpen, Is.False); await db.DisposeAsync(); } @@ -96,7 +95,7 @@ public async Task OpenInMemoryAsync_WhenCalledTwice_ShouldCloseFirstConnection() await db.OpenInMemoryAsync(); // Should close first connection // Assert - db.IsOpen.Should().BeTrue(); + Assert.That(db.IsOpen, Is.True); await db.DisposeAsync(); } @@ -112,8 +111,8 @@ public void GetDatabasePath_ShouldReturnConsistentPath() var path2 = ProjectDatabase.GetDatabasePath(projectPath); // Assert - path1.Should().Be(path2); - path1.Should().EndWith(".db"); + Assert.That(path1, Is.EqualTo(path2)); + Assert.That(path1, Does.EndWith(".db")); } [Test] @@ -127,9 +126,9 @@ public void ComputeProjectHash_ShouldReturnConsistentHash() var hash2 = ProjectDatabase.ComputeProjectHash(projectPath); // Assert - hash1.Should().Be(hash2); - hash1.Should().HaveLength(16); - hash1.Should().MatchRegex("^[a-f0-9]+$"); + Assert.That(hash1, Is.EqualTo(hash2)); + Assert.That(hash1, Has.Length.EqualTo(16)); + Assert.That(hash1, Does.Match("^[a-f0-9]+$")); } #endregion @@ -143,12 +142,12 @@ public async Task GetOrCreateProjectAsync_CreatesNewProject() var projectId = await _db.GetOrCreateProjectAsync("/test/path", "TestProject"); // Assert - projectId.Should().BeGreaterThan(0); + Assert.That(projectId, Is.GreaterThan(0)); var project = await _db.GetProjectByIdAsync(projectId); - project.Should().NotBeNull(); - project!.Name.Should().Be("TestProject"); - project.RootPath.Should().Be("/test/path"); + Assert.That(project, Is.Not.Null); + Assert.That(project!.Name, Is.EqualTo("TestProject")); + Assert.That(project.RootPath, Is.EqualTo("/test/path")); } [Test] @@ -161,7 +160,7 @@ public async Task GetOrCreateProjectAsync_ReturnsExistingProject() var projectId2 = await _db.GetOrCreateProjectAsync("/test/path", "TestProject"); // Assert - projectId1.Should().Be(projectId2); + Assert.That(projectId2, Is.EqualTo(projectId1)); } [Test] @@ -179,7 +178,7 @@ public async Task GetOrCreateProjectAsync_UpdatesOpenedAt() // Assert var project2 = await _db.GetProjectByIdAsync(projectId); - project2!.OpenedAt.Should().BeAfter(firstOpenedAt); + Assert.That(project2!.OpenedAt, Is.GreaterThan(firstOpenedAt)); } [Test] @@ -189,7 +188,7 @@ public async Task GetProjectByIdAsync_ReturnsNull_WhenNotFound() var project = await _db.GetProjectByIdAsync(999999); // Assert - project.Should().BeNull(); + Assert.That(project, Is.Null); } [Test] @@ -202,9 +201,9 @@ public async Task GetProjectByPathAsync_ReturnsProject() var project = await _db.GetProjectByPathAsync("/test/path"); // Assert - project.Should().NotBeNull(); - project!.Id.Should().Be(projectId); - project.Name.Should().Be("TestProject"); + Assert.That(project, Is.Not.Null); + Assert.That(project!.Id, Is.EqualTo(projectId)); + Assert.That(project.Name, Is.EqualTo("TestProject")); } [Test] @@ -218,7 +217,7 @@ public async Task UpdateProjectStatsAsync_UpdatesSolutionCount() // Assert var project = await _db.GetProjectByIdAsync(projectId); - project!.SolutionCount.Should().Be(5); + Assert.That(project!.SolutionCount, Is.EqualTo(5)); } [Test] @@ -232,9 +231,9 @@ public async Task UpdateProjectStatsAsync_UpdatesMultipleStats() // Assert var project = await _db.GetProjectByIdAsync(projectId); - project!.SolutionCount.Should().Be(2); - project.ProjectCount.Should().Be(10); - project.FileCount.Should().Be(100); + Assert.That(project!.SolutionCount, Is.EqualTo(2)); + Assert.That(project.ProjectCount, Is.EqualTo(10)); + Assert.That(project.FileCount, Is.EqualTo(100)); } [Test] @@ -248,7 +247,7 @@ public async Task SetProjectStructureAsync_StoresKeyValue() // Assert var result = await _db.GetProjectStructureAsync(projectId, "test-key"); - result.Should().Be("{\"value\":42}"); + Assert.That(result, Is.EqualTo("{\"value\":42}")); } [Test] @@ -263,7 +262,7 @@ public async Task SetProjectStructureAsync_UpdatesExistingKey() // Assert var result = await _db.GetProjectStructureAsync(projectId, "test-key"); - result.Should().Be("{\"value\":100}"); + Assert.That(result, Is.EqualTo("{\"value\":100}")); } [Test] @@ -276,7 +275,7 @@ public async Task GetProjectStructureAsync_ReturnsNull_WhenKeyNotFound() var result = await _db.GetProjectStructureAsync(projectId, "nonexistent-key"); // Assert - result.Should().BeNull(); + Assert.That(result, Is.Null); } [Test] @@ -292,8 +291,10 @@ public async Task GetProjectStructureKeysAsync_ReturnsAllKeys() var keys = await _db.GetProjectStructureKeysAsync(projectId); // Assert - keys.Should().HaveCount(3); - keys.Should().Contain(new[] { "key1", "key2", "key3" }); + Assert.That(keys, Has.Count.EqualTo(3)); + Assert.That(keys, Does.Contain("key1")); + Assert.That(keys, Does.Contain("key2")); + Assert.That(keys, Does.Contain("key3")); } [Test] @@ -307,7 +308,7 @@ public async Task DeleteProjectAsync_RemovesProject() // Assert var project = await _db.GetProjectByIdAsync(projectId); - project.Should().BeNull(); + Assert.That(project, Is.Null); } [Test] @@ -320,11 +321,11 @@ public async Task GetDatabaseStatsAsync_ReturnsCorrectCounts() var stats = await _db.GetDatabaseStatsAsync(); // Assert - stats.Should().ContainKey("projects"); - stats["projects"].Should().Be(1); - stats.Should().ContainKey("files"); - stats.Should().ContainKey("symbols"); - stats.Should().ContainKey("symbol_references"); + Assert.That(stats, Does.ContainKey("projects")); + Assert.That(stats["projects"], Is.EqualTo(1)); + Assert.That(stats, Does.ContainKey("files")); + Assert.That(stats, Does.ContainKey("symbols")); + Assert.That(stats, Does.ContainKey("symbol_references")); } #endregion @@ -341,14 +342,14 @@ public async Task UpsertFileAsync_CreatesNewFile() var fileId = await _db.UpsertFileAsync(projectId, "Program.cs", "hash123", 1000, "csharp"); // Assert - fileId.Should().BeGreaterThan(0); + Assert.That(fileId, Is.GreaterThan(0)); var file = await _db.GetFileAsync(projectId, "Program.cs"); - file.Should().NotBeNull(); - file!.RelativePath.Should().Be("Program.cs"); - file.ContentHash.Should().Be("hash123"); - file.SizeBytes.Should().Be(1000); - file.Language.Should().Be("csharp"); + Assert.That(file, Is.Not.Null); + Assert.That(file!.RelativePath, Is.EqualTo("Program.cs")); + Assert.That(file.ContentHash, Is.EqualTo("hash123")); + Assert.That(file.SizeBytes, Is.EqualTo(1000)); + Assert.That(file.Language, Is.EqualTo("csharp")); } [Test] @@ -362,11 +363,11 @@ public async Task UpsertFileAsync_UpdatesExistingFile() var fileId2 = await _db.UpsertFileAsync(projectId, "Program.cs", "hash456", 2000, "csharp"); // Assert - fileId1.Should().Be(fileId2); + Assert.That(fileId2, Is.EqualTo(fileId1)); var file = await _db.GetFileAsync(projectId, "Program.cs"); - file!.ContentHash.Should().Be("hash456"); - file.SizeBytes.Should().Be(2000); + Assert.That(file!.ContentHash, Is.EqualTo("hash456")); + Assert.That(file.SizeBytes, Is.EqualTo(2000)); } [Test] @@ -379,7 +380,7 @@ public async Task GetFileAsync_ReturnsNull_WhenNotFound() var file = await _db.GetFileAsync(projectId, "NonExistent.cs"); // Assert - file.Should().BeNull(); + Assert.That(file, Is.Null); } [Test] @@ -395,8 +396,8 @@ public async Task GetAllFilesAsync_ReturnsAllFiles() var files = await _db.GetAllFilesAsync(projectId); // Assert - files.Should().HaveCount(3); - files.Should().OnlyContain(f => f.ProjectId == projectId); + Assert.That(files, Has.Count.EqualTo(3)); + Assert.That(files, Has.All.Matches(f => f.ProjectId == projectId)); } [Test] @@ -417,8 +418,8 @@ public async Task GetStaleFilesAsync_DetectsChangedFiles() var staleFiles = await _db.GetStaleFilesAsync(projectId, currentHashes); // Assert - staleFiles.Should().HaveCount(1); - staleFiles.First().RelativePath.Should().Be("File2.cs"); + Assert.That(staleFiles, Has.Count.EqualTo(1)); + Assert.That(staleFiles.First().RelativePath, Is.EqualTo("File2.cs")); } [Test] @@ -438,8 +439,8 @@ public async Task GetStaleFilesAsync_DetectsMissingFiles() var staleFiles = await _db.GetStaleFilesAsync(projectId, currentHashes); // Assert - staleFiles.Should().HaveCount(1); - staleFiles.First().RelativePath.Should().Be("File2.cs"); + Assert.That(staleFiles, Has.Count.EqualTo(1)); + Assert.That(staleFiles.First().RelativePath, Is.EqualTo("File2.cs")); } [Test] @@ -456,8 +457,8 @@ public async Task GetDeletedFilesAsync_FindsRemovedFiles() var deletedFiles = await _db.GetDeletedFilesAsync(projectId, currentPaths); // Assert - deletedFiles.Should().HaveCount(1); - deletedFiles.First().RelativePath.Should().Be("File2.cs"); + Assert.That(deletedFiles, Has.Count.EqualTo(1)); + Assert.That(deletedFiles.First().RelativePath, Is.EqualTo("File2.cs")); } [Test] @@ -472,7 +473,7 @@ public async Task DeleteFileAsync_RemovesFile() // Assert var file = await _db.GetFileAsync(projectId, "File1.cs"); - file.Should().BeNull(); + Assert.That(file, Is.Null); } [Test] @@ -487,7 +488,7 @@ public async Task DeleteFileByPathAsync_RemovesFile() // Assert var file = await _db.GetFileAsync(projectId, "File1.cs"); - file.Should().BeNull(); + Assert.That(file, Is.Null); } [Test] @@ -502,7 +503,7 @@ public async Task GetFileCountAsync_ReturnsCorrectCount() var count = await _db.GetFileCountAsync(projectId); // Assert - count.Should().Be(2); + Assert.That(count, Is.EqualTo(2)); } [Test] @@ -522,7 +523,7 @@ public async Task UpsertFilesBatchAsync_InsertsMultipleFiles() // Assert var allFiles = await _db.GetAllFilesAsync(projectId); - allFiles.Should().HaveCount(3); + Assert.That(allFiles, Has.Count.EqualTo(3)); } [Test] @@ -548,7 +549,7 @@ public async Task UpsertFilesBatchAsync_IsAtomic_RollsBackOnError() await _db.UpsertFilesBatchAsync(projectId, filesUpdate); var countAfter = await _db.GetFileCountAsync(projectId); - countAfter.Should().Be(3); // 3 total files + Assert.That(countAfter, Is.EqualTo(3)); // 3 total files } #endregion @@ -581,12 +582,12 @@ public async Task UpsertSymbolAsync_CreatesNewSymbol() var symbolId = await _db.UpsertSymbolAsync(symbol); // Assert - symbolId.Should().BeGreaterThan(0); + Assert.That(symbolId, Is.GreaterThan(0)); var retrievedSymbol = await _db.GetSymbolByIdAsync(symbolId); - retrievedSymbol.Should().NotBeNull(); - retrievedSymbol!.Name.Should().Be("TestClass"); - retrievedSymbol.Kind.Should().Be("Class"); + Assert.That(retrievedSymbol, Is.Not.Null); + Assert.That(retrievedSymbol!.Name, Is.EqualTo("TestClass")); + Assert.That(retrievedSymbol.Kind, Is.EqualTo("Class")); } [Test] @@ -604,8 +605,8 @@ public async Task FindSymbolsByNameAsync_FindsPartialMatches() var symbols = await _db.FindSymbolsByNameAsync("Test"); // Assert - symbols.Should().HaveCount(2); - symbols.Should().OnlyContain(s => s.Name.Contains("Test")); + Assert.That(symbols, Has.Count.EqualTo(2)); + Assert.That(symbols, Has.All.Matches(s => s.Name.Contains("Test"))); } [Test] @@ -622,8 +623,8 @@ public async Task FindSymbolsByNameAsync_FiltersOnKind() var symbols = await _db.FindSymbolsByNameAsync("Test", kind: "Class"); // Assert - symbols.Should().HaveCount(1); - symbols.First().Name.Should().Be("TestClass"); + Assert.That(symbols, Has.Count.EqualTo(1)); + Assert.That(symbols.First().Name, Is.EqualTo("TestClass")); } [Test] @@ -640,8 +641,8 @@ public async Task FindSymbolsByExactNameAsync_FindsExactMatch() var symbols = await _db.FindSymbolsByExactNameAsync("TestClass"); // Assert - symbols.Should().HaveCount(1); - symbols.First().Name.Should().Be("TestClass"); + Assert.That(symbols, Has.Count.EqualTo(1)); + Assert.That(symbols.First().Name, Is.EqualTo("TestClass")); } [Test] @@ -659,11 +660,11 @@ public async Task GetSymbolsInFileAsync_ReturnsAllSymbols() var symbols = await _db.GetSymbolsInFileAsync(fileId); // Assert - symbols.Should().HaveCount(3); + Assert.That(symbols, Has.Count.EqualTo(3)); // Should be ordered by line, column - symbols[0].Line.Should().Be(1); - symbols[1].Line.Should().Be(5); - symbols[2].Line.Should().Be(10); + Assert.That(symbols[0].Line, Is.EqualTo(1)); + Assert.That(symbols[1].Line, Is.EqualTo(5)); + Assert.That(symbols[2].Line, Is.EqualTo(10)); } [Test] @@ -684,8 +685,8 @@ public async Task SearchSymbolsAsync_FiltersWithMultipleCriteria() namespaces: new[] { "Test.Namespace" }); // Assert - symbols.Should().HaveCount(1); - symbols.First().Name.Should().Be("TestClass"); + Assert.That(symbols, Has.Count.EqualTo(1)); + Assert.That(symbols.First().Name, Is.EqualTo("TestClass")); } [Test] @@ -702,7 +703,7 @@ public async Task SearchSymbolsAsync_ReturnsAll_WhenNoFilters() var symbols = await _db.SearchSymbolsAsync(); // Assert - symbols.Should().HaveCount(2); + Assert.That(symbols, Has.Count.EqualTo(2)); } [Test] @@ -720,10 +721,10 @@ public async Task GetSymbolCountsByKindAsync_ReturnsCorrectCounts() var counts = await _db.GetSymbolCountsByKindAsync(); // Assert - counts.Should().ContainKey("Class"); - counts["Class"].Should().Be(2); - counts.Should().ContainKey("Method"); - counts["Method"].Should().Be(1); + Assert.That(counts, Does.ContainKey("Class")); + Assert.That(counts["Class"], Is.EqualTo(2)); + Assert.That(counts, Does.ContainKey("Method")); + Assert.That(counts["Method"], Is.EqualTo(1)); } [Test] @@ -741,7 +742,7 @@ public async Task DeleteSymbolsForFileAsync_RemovesAllSymbols() // Assert var symbols = await _db.GetSymbolsInFileAsync(fileId); - symbols.Should().BeEmpty(); + Assert.That(symbols, Is.Empty); } [Test] @@ -763,7 +764,7 @@ public async Task UpsertSymbolsBatchAsync_InsertsMultipleSymbols() // Assert var allSymbols = await _db.GetSymbolsInFileAsync(fileId); - allSymbols.Should().HaveCount(3); + Assert.That(allSymbols, Has.Count.EqualTo(3)); } #endregion @@ -793,7 +794,7 @@ public async Task UpsertReferenceAsync_CreatesNewReference() var refId = await _db.UpsertReferenceAsync(reference); // Assert - refId.Should().BeGreaterThan(0); + Assert.That(refId, Is.GreaterThan(0)); } [Test] @@ -819,8 +820,8 @@ await _db.UpsertReferenceAsync(new DbReference var callers = await _db.FindCallersAsync(calleeId); // Assert - callers.Should().HaveCount(1); - callers.First().Caller.Name.Should().Be("Caller"); + Assert.That(callers, Has.Count.EqualTo(1)); + Assert.That(callers.First().Caller.Name, Is.EqualTo("Caller")); } [Test] @@ -846,8 +847,8 @@ await _db.UpsertReferenceAsync(new DbReference var callees = await _db.FindCalleesAsync(callerId); // Assert - callees.Should().HaveCount(1); - callees.First().Callee.Name.Should().Be("Callee"); + Assert.That(callees, Has.Count.EqualTo(1)); + Assert.That(callees.First().Callee.Name, Is.EqualTo("Callee")); } [Test] @@ -868,9 +869,9 @@ public async Task GetCallChainAsync_Backward_FindsCallers() var chain = await _db.GetCallChainAsync(cId, ProjectDatabase.CallChainDirection.Backward, maxDepth: 10); // Assert - chain.Should().HaveCount(2); - chain.Should().Contain(s => s.Name == "MethodA"); - chain.Should().Contain(s => s.Name == "MethodB"); + Assert.That(chain, Has.Count.EqualTo(2)); + Assert.That(chain, Does.Contain(chain.First(s => s.Name == "MethodA"))); + Assert.That(chain, Does.Contain(chain.First(s => s.Name == "MethodB"))); } [Test] @@ -891,9 +892,9 @@ public async Task GetCallChainAsync_Forward_FindsCallees() var chain = await _db.GetCallChainAsync(aId, ProjectDatabase.CallChainDirection.Forward, maxDepth: 10); // Assert - chain.Should().HaveCount(2); - chain.Should().Contain(s => s.Name == "MethodB"); - chain.Should().Contain(s => s.Name == "MethodC"); + Assert.That(chain, Has.Count.EqualTo(2)); + Assert.That(chain, Does.Contain(chain.First(s => s.Name == "MethodB"))); + Assert.That(chain, Does.Contain(chain.First(s => s.Name == "MethodC"))); } [Test] @@ -916,10 +917,10 @@ public async Task GetCallChainAsync_RespectsMaxDepth() var chain = await _db.GetCallChainAsync(aId, ProjectDatabase.CallChainDirection.Forward, maxDepth: 2); // Assert - Should only find B and C, not D - chain.Should().HaveCount(2); - chain.Should().Contain(s => s.Name == "MethodB"); - chain.Should().Contain(s => s.Name == "MethodC"); - chain.Should().NotContain(s => s.Name == "MethodD"); + Assert.That(chain, Has.Count.EqualTo(2)); + Assert.That(chain, Does.Contain(chain.First(s => s.Name == "MethodB"))); + Assert.That(chain, Does.Contain(chain.First(s => s.Name == "MethodC"))); + Assert.That(chain, Does.Not.Contain(chain.FirstOrDefault(s => s.Name == "MethodD"))); } [Test] @@ -940,7 +941,7 @@ public async Task GetReferencesToSymbolAsync_ReturnsAllReferences() var references = await _db.GetReferencesToSymbolAsync(calleeId); // Assert - references.Should().HaveCount(2); + Assert.That(references, Has.Count.EqualTo(2)); } [Test] @@ -961,10 +962,10 @@ public async Task GetReferenceCountsByKindAsync_ReturnsCorrectCounts() var counts = await _db.GetReferenceCountsByKindAsync(); // Assert - counts.Should().ContainKey("Call"); - counts["Call"].Should().Be(2); - counts.Should().ContainKey("TypeUsage"); - counts["TypeUsage"].Should().Be(1); + Assert.That(counts, Does.ContainKey("Call")); + Assert.That(counts["Call"], Is.EqualTo(2)); + Assert.That(counts, Does.ContainKey("TypeUsage")); + Assert.That(counts["TypeUsage"], Is.EqualTo(1)); } [Test] @@ -984,7 +985,7 @@ public async Task DeleteReferencesForFileAsync_RemovesAllReferences() // Assert var references = await _db.GetReferencesToSymbolAsync(symbol2Id); - references.Should().BeEmpty(); + Assert.That(references, Is.Empty); } [Test] @@ -1009,7 +1010,7 @@ public async Task UpsertReferencesBatchAsync_InsertsMultipleReferences() // Assert var callees = await _db.FindCalleesAsync(symbol1Id); - callees.Should().HaveCount(2); + Assert.That(callees, Has.Count.EqualTo(2)); } #endregion @@ -1026,7 +1027,7 @@ public async Task GetAllFilesAsync_ReturnsEmpty_WhenNoFiles() var files = await _db.GetAllFilesAsync(projectId); // Assert - files.Should().BeEmpty(); + Assert.That(files, Is.Empty); } [Test] @@ -1040,7 +1041,7 @@ public async Task GetSymbolsInFileAsync_ReturnsEmpty_WhenNoSymbols() var symbols = await _db.GetSymbolsInFileAsync(fileId); // Assert - symbols.Should().BeEmpty(); + Assert.That(symbols, Is.Empty); } [Test] @@ -1055,7 +1056,7 @@ public async Task FindCallersAsync_ReturnsEmpty_WhenNoCallers() var callers = await _db.FindCallersAsync(symbolId); // Assert - callers.Should().BeEmpty(); + Assert.That(callers, Is.Empty); } [Test] @@ -1070,7 +1071,7 @@ public async Task GetCallChainAsync_ReturnsEmpty_WhenNoChain() var chain = await _db.GetCallChainAsync(symbolId, ProjectDatabase.CallChainDirection.Forward); // Assert - chain.Should().BeEmpty(); + Assert.That(chain, Is.Empty); } [Test] @@ -1081,17 +1082,15 @@ public async Task ExecuteInTransactionAsync_RollsBackOnException() var fileCountBefore = await _db.GetFileCountAsync(projectId); // Act & Assert - var act = async () => await _db.ExecuteInTransactionAsync(async (conn, tx) => + Assert.ThrowsAsync(async () => await _db.ExecuteInTransactionAsync(async (conn, tx) => { await _db.UpsertFileAsync(projectId, "File1.cs", "hash1", 100, "csharp"); throw new InvalidOperationException("Test exception"); - }); - - await act.Should().ThrowAsync(); + })); // Assert - transaction should have rolled back var fileCountAfter = await _db.GetFileCountAsync(projectId); - fileCountAfter.Should().Be(fileCountBefore); + Assert.That(fileCountAfter, Is.EqualTo(fileCountBefore)); } [Test] @@ -1106,9 +1105,9 @@ public async Task UpdateProjectStatsAsync_IgnoresNullValues() // Assert var project = await _db.GetProjectByIdAsync(projectId); - project!.SolutionCount.Should().Be(7); - project.ProjectCount.Should().Be(10); // unchanged - project.FileCount.Should().Be(20); // unchanged + Assert.That(project!.SolutionCount, Is.EqualTo(7)); + Assert.That(project.ProjectCount, Is.EqualTo(10)); // unchanged + Assert.That(project.FileCount, Is.EqualTo(20)); // unchanged } [Test] @@ -1133,7 +1132,7 @@ public async Task SearchSymbolsAsync_HandlesEmptyFilters() namespaces: Array.Empty()); // Assert - symbols.Should().HaveCount(1); + Assert.That(symbols, Has.Count.EqualTo(1)); } #endregion diff --git a/tests/MCPsharp.Tests/Services/FeatureTracerServiceTests.cs b/tests/MCPsharp.Tests/Services/FeatureTracerServiceTests.cs index d8a41a0..a8f0a06 100644 --- a/tests/MCPsharp.Tests/Services/FeatureTracerServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/FeatureTracerServiceTests.cs @@ -1,4 +1,4 @@ -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; @@ -8,11 +8,11 @@ namespace MCPsharp.Tests.Services; /// public class FeatureTracerServiceTests { - [Fact] + [Test] public void Placeholder_Test() { // This is a placeholder to allow the project to compile // Phase 2 agents will implement actual tests - Assert.True(true); + Assert.That(true, Is.True); } } diff --git a/tests/MCPsharp.Tests/Services/FileOperationsServiceTests.cs b/tests/MCPsharp.Tests/Services/FileOperationsServiceTests.cs index a865f97..d23ce0f 100644 --- a/tests/MCPsharp.Tests/Services/FileOperationsServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/FileOperationsServiceTests.cs @@ -1,16 +1,18 @@ -using FluentAssertions; using MCPsharp.Models; using MCPsharp.Services; -using Xunit; +using NUnit.Framework; +using FileInfo = MCPsharp.Models.FileInfo; namespace MCPsharp.Tests.Services; -public class FileOperationsServiceTests : IDisposable +[TestFixture] +public class FileOperationsServiceTests { - private readonly string _testRoot; - private readonly FileOperationsService _service; + private string _testRoot = null!; + private FileOperationsService _service = null!; - public FileOperationsServiceTests() + [SetUp] + public void SetUp() { // Create a temporary test directory _testRoot = Path.Combine(Path.GetTempPath(), $"mcpsharp-test-{Guid.NewGuid()}"); @@ -18,7 +20,8 @@ public FileOperationsServiceTests() _service = new FileOperationsService(_testRoot); } - public void Dispose() + [TearDown] + public void TearDown() { // Clean up test directory if (Directory.Exists(_testRoot)) @@ -27,18 +30,17 @@ public void Dispose() } } - [Fact] + [Test] public void Constructor_ShouldThrowException_WhenDirectoryDoesNotExist() { // Arrange var nonExistentPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); // Act & Assert - Action act = () => new FileOperationsService(nonExistentPath); - act.Should().Throw(); + Assert.Throws(() => new FileOperationsService(nonExistentPath)); } - [Fact] + [Test] public void ListFiles_ShouldReturnAllFiles_WhenNoPatternSpecified() { // Arrange @@ -50,12 +52,12 @@ public void ListFiles_ShouldReturnAllFiles_WhenNoPatternSpecified() var result = _service.ListFiles(); // Assert - result.TotalFiles.Should().Be(3); - result.Files.Should().HaveCount(3); - result.Pattern.Should().BeNull(); + Assert.That(result.TotalFiles, Is.EqualTo(3)); + Assert.That(result.Files, Has.Count.EqualTo(3)); + Assert.That(result.Pattern, Is.Null); } - [Fact] + [Test] public void ListFiles_ShouldFilterByCsFiles_WhenPatternSpecified() { // Arrange @@ -67,13 +69,13 @@ public void ListFiles_ShouldFilterByCsFiles_WhenPatternSpecified() var result = _service.ListFiles("**/*.cs"); // Assert - result.TotalFiles.Should().Be(2); - result.Files.Should().HaveCount(2); - result.Files.Should().OnlyContain(f => f.RelativePath.EndsWith(".cs")); - result.Pattern.Should().Be("**/*.cs"); + Assert.That(result.TotalFiles, Is.EqualTo(2)); + Assert.That(result.Files, Has.Count.EqualTo(2)); + Assert.That(result.Files, Has.All.Matches(f => f.RelativePath.EndsWith(".cs"))); + Assert.That(result.Pattern, Is.EqualTo("**/*.cs")); } - [Fact] + [Test] public void ListFiles_ShouldExcludeHiddenFiles_ByDefault() { // Arrange @@ -85,11 +87,11 @@ public void ListFiles_ShouldExcludeHiddenFiles_ByDefault() var result = _service.ListFiles(); // Assert - result.Files.Should().HaveCount(1); - result.Files.Should().OnlyContain(f => !f.IsHidden); + Assert.That(result.Files, Has.Count.EqualTo(1)); + Assert.That(result.Files, Has.All.Matches(f => !f.IsHidden)); } - [Fact] + [Test] public void ListFiles_ShouldIncludeHiddenFiles_WhenRequested() { // Arrange @@ -100,10 +102,10 @@ public void ListFiles_ShouldIncludeHiddenFiles_WhenRequested() var result = _service.ListFiles(includeHidden: true); // Assert - result.Files.Should().HaveCount(2); + Assert.That(result.Files, Has.Count.EqualTo(2)); } - [Fact] + [Test] public async Task ReadFileAsync_ShouldReturnContent_WhenFileExists() { // Arrange @@ -114,37 +116,37 @@ public async Task ReadFileAsync_ShouldReturnContent_WhenFileExists() var result = await _service.ReadFileAsync("test.txt"); // Assert - result.Success.Should().BeTrue(); - result.Content.Should().Be(content); - result.LineCount.Should().Be(3); - result.Encoding.Should().Be("utf-8"); - result.Error.Should().BeNull(); + Assert.That(result.Success, Is.True); + Assert.That(result.Content, Is.EqualTo(content)); + Assert.That(result.LineCount, Is.EqualTo(3)); + Assert.That(result.Encoding, Is.EqualTo("utf-8")); + Assert.That(result.Error, Is.Null); } - [Fact] + [Test] public async Task ReadFileAsync_ShouldFail_WhenFileDoesNotExist() { // Act var result = await _service.ReadFileAsync("nonexistent.txt"); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("not found"); - result.Content.Should().BeNull(); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("not found")); + Assert.That(result.Content, Is.Null); } - [Fact] + [Test] public async Task ReadFileAsync_ShouldFail_WhenPathOutsideRoot() { // Act var result = await _service.ReadFileAsync("../outside.txt"); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("outside project root"); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("outside project root")); } - [Fact] + [Test] public async Task WriteFileAsync_ShouldCreateNewFile() { // Arrange @@ -154,15 +156,15 @@ public async Task WriteFileAsync_ShouldCreateNewFile() var result = await _service.WriteFileAsync("newfile.txt", content); // Assert - result.Success.Should().BeTrue(); - result.Created.Should().BeTrue(); - result.BytesWritten.Should().BeGreaterThan(0); + Assert.That(result.Success, Is.True); + Assert.That(result.Created, Is.True); + Assert.That(result.BytesWritten, Is.GreaterThan(0)); var fileContent = File.ReadAllText(Path.Combine(_testRoot, "newfile.txt")); - fileContent.Should().Be(content); + Assert.That(fileContent, Is.EqualTo(content)); } - [Fact] + [Test] public async Task WriteFileAsync_ShouldOverwriteExistingFile() { // Arrange @@ -173,14 +175,14 @@ public async Task WriteFileAsync_ShouldOverwriteExistingFile() var result = await _service.WriteFileAsync("existing.txt", newContent); // Assert - result.Success.Should().BeTrue(); - result.Created.Should().BeFalse(); + Assert.That(result.Success, Is.True); + Assert.That(result.Created, Is.False); var fileContent = File.ReadAllText(Path.Combine(_testRoot, "existing.txt")); - fileContent.Should().Be(newContent); + Assert.That(fileContent, Is.EqualTo(newContent)); } - [Fact] + [Test] public async Task WriteFileAsync_ShouldCreateDirectories_WhenRequested() { // Arrange @@ -190,25 +192,25 @@ public async Task WriteFileAsync_ShouldCreateDirectories_WhenRequested() var result = await _service.WriteFileAsync("subdir1/subdir2/file.txt", content, createDirectories: true); // Assert - result.Success.Should().BeTrue(); - result.Created.Should().BeTrue(); + Assert.That(result.Success, Is.True); + Assert.That(result.Created, Is.True); var filePath = Path.Combine(_testRoot, "subdir1/subdir2/file.txt"); - File.Exists(filePath).Should().BeTrue(); + Assert.That(File.Exists(filePath), Is.True); } - [Fact] + [Test] public async Task WriteFileAsync_ShouldFail_WhenPathOutsideRoot() { // Act var result = await _service.WriteFileAsync("../outside.txt", "content"); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("outside project root"); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("outside project root")); } - [Fact] + [Test] public async Task EditFileAsync_ShouldApplyReplaceEdit_SingleLine() { // Arrange @@ -230,12 +232,12 @@ public async Task EditFileAsync_ShouldApplyReplaceEdit_SingleLine() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeTrue(); - result.EditsApplied.Should().Be(1); - result.NewContent.Should().Be("int x = 10;"); + Assert.That(result.Success, Is.True); + Assert.That(result.EditsApplied, Is.EqualTo(1)); + Assert.That(result.NewContent, Is.EqualTo("int x = 10;")); } - [Fact] + [Test] public async Task EditFileAsync_ShouldApplyInsertEdit() { // Arrange @@ -257,11 +259,11 @@ public async Task EditFileAsync_ShouldApplyInsertEdit() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeTrue(); - result.NewContent.Should().Be("int x = 5; // comment"); + Assert.That(result.Success, Is.True); + Assert.That(result.NewContent, Is.EqualTo("int x = 5; // comment")); } - [Fact] + [Test] public async Task EditFileAsync_ShouldApplyDeleteEdit() { // Arrange @@ -283,11 +285,11 @@ public async Task EditFileAsync_ShouldApplyDeleteEdit() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeTrue(); - result.NewContent.Should().Be("int x = 5; "); + Assert.That(result.Success, Is.True); + Assert.That(result.NewContent, Is.EqualTo("int x = 5; ")); } - [Fact] + [Test] public async Task EditFileAsync_ShouldApplyMultipleEdits_InCorrectOrder() { // Arrange @@ -305,12 +307,12 @@ public async Task EditFileAsync_ShouldApplyMultipleEdits_InCorrectOrder() var result = await _service.EditFileAsync("test.txt", edits); // Assert - result.Success.Should().BeTrue(); - result.EditsApplied.Should().Be(3); - result.NewContent.Should().Be("Line 1 INSERTED\nModified 2\nLine "); + Assert.That(result.Success, Is.True); + Assert.That(result.EditsApplied, Is.EqualTo(3)); + Assert.That(result.NewContent, Is.EqualTo("Line 1 INSERTED\nModified 2\nLine ")); } - [Fact] + [Test] public async Task EditFileAsync_ShouldApplyMultiLineReplace() { // Arrange @@ -333,11 +335,11 @@ public async Task EditFileAsync_ShouldApplyMultiLineReplace() var result = await _service.EditFileAsync("test.txt", edits); // Assert - result.Success.Should().BeTrue(); - result.NewContent.Should().Be("Line 1\nReplaced\nMultiple\nLines\nLine 4"); + Assert.That(result.Success, Is.True); + Assert.That(result.NewContent, Is.EqualTo("Line 1\nReplaced\nMultiple\nLines\nLine 4")); } - [Fact] + [Test] public async Task EditFileAsync_ShouldFail_WhenFileDoesNotExist() { // Arrange @@ -350,11 +352,11 @@ public async Task EditFileAsync_ShouldFail_WhenFileDoesNotExist() var result = await _service.EditFileAsync("nonexistent.txt", edits); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("not found"); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("not found")); } - [Fact] + [Test] public async Task EditFileAsync_ShouldFail_WhenPathOutsideRoot() { // Arrange @@ -367,13 +369,13 @@ public async Task EditFileAsync_ShouldFail_WhenPathOutsideRoot() var result = await _service.EditFileAsync("../outside.txt", edits); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("outside project root"); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("outside project root")); } // Column Indexing Validation Tests - - [Fact] + + [Test] public async Task EditFileAsync_ShouldFail_WhenStartLineIsNegative() { // Arrange @@ -387,13 +389,13 @@ public async Task EditFileAsync_ShouldFail_WhenStartLineIsNegative() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("StartLine -1 is out of range"); - result.Error.Should().Contain("Invalid edit position"); - result.Error.Should().Contain("0-based indexing"); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("StartLine -1 is out of range")); + Assert.That(result.Error, Does.Contain("Invalid edit position")); + Assert.That(result.Error, Does.Contain("0-based indexing")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldFail_WhenStartLineExceedsFileLength() { // Arrange @@ -407,12 +409,12 @@ public async Task EditFileAsync_ShouldFail_WhenStartLineExceedsFileLength() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("StartLine 5 is out of range"); - result.Error.Should().Contain("File has 1 lines (0-0)"); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("StartLine 5 is out of range")); + Assert.That(result.Error, Does.Contain("File has 1 lines (0-0)")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldFail_WhenEndLineExceedsFileLength() { // Arrange @@ -426,11 +428,11 @@ public async Task EditFileAsync_ShouldFail_WhenEndLineExceedsFileLength() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("EndLine 5 is out of range"); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("EndLine 5 is out of range")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldFail_WhenStartColumnIsNegative() { // Arrange @@ -444,12 +446,12 @@ public async Task EditFileAsync_ShouldFail_WhenStartColumnIsNegative() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("StartColumn -1 is out of range for line 0"); - result.Error.Should().Contain("Line 0 has 10 characters. Valid positions: 0-9 for replacements, 0-10 for insertions."); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("StartColumn -1 is out of range for line 0")); + Assert.That(result.Error, Does.Contain("Line 0 has 10 characters. Valid positions: 0-9 for replacements, 0-10 for insertions.")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldFail_WhenStartColumnExceedsLineLength() { // Arrange @@ -463,12 +465,12 @@ public async Task EditFileAsync_ShouldFail_WhenStartColumnExceedsLineLength() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("StartColumn 15 is out of range for line 0"); - result.Error.Should().Contain("Line 0 has 10 characters. Valid positions: 0-9 for replacements, 0-10 for insertions."); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("StartColumn 15 is out of range for line 0")); + Assert.That(result.Error, Does.Contain("Line 0 has 10 characters. Valid positions: 0-9 for replacements, 0-10 for insertions.")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldFail_WhenEndColumnExceedsLineLength() { // Arrange @@ -482,11 +484,11 @@ public async Task EditFileAsync_ShouldFail_WhenEndColumnExceedsLineLength() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("EndColumn 15 is out of range for line 0"); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("EndColumn 15 is out of range for line 0")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldFail_WhenStartColumnGreaterThanEndColumn() { // Arrange @@ -500,11 +502,11 @@ public async Task EditFileAsync_ShouldFail_WhenStartColumnGreaterThanEndColumn() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("Invalid edit range: start position (0,8) is after end position (0,5)"); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("Invalid edit range: start position (0,8) is after end position (0,5)")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldFail_WhenStartLineGreaterThanEndLine() { // Arrange @@ -518,11 +520,11 @@ public async Task EditFileAsync_ShouldFail_WhenStartLineGreaterThanEndLine() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeFalse(); - result.Error.Should().Contain("Invalid edit range: start position (1,0) is after end position (0,1)"); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Does.Contain("Invalid edit range: start position (1,0) is after end position (0,1)")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldSucceed_WhenEditAtValidBounds() { // Arrange - test editing at exact line boundaries @@ -536,11 +538,11 @@ public async Task EditFileAsync_ShouldSucceed_WhenEditAtValidBounds() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeTrue(); - result.NewContent.Should().Be("xyz"); + Assert.That(result.Success, Is.True); + Assert.That(result.NewContent, Is.EqualTo("xyz")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldSucceed_WhenEditAtStartOfLine() { // Arrange @@ -554,11 +556,11 @@ public async Task EditFileAsync_ShouldSucceed_WhenEditAtStartOfLine() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeTrue(); - result.NewContent.Should().Be("// comment\nint x = 5;"); + Assert.That(result.Success, Is.True); + Assert.That(result.NewContent, Is.EqualTo("// comment\nint x = 5;")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldSucceed_WhenEditAtEndOfLine() { // Arrange @@ -572,11 +574,11 @@ public async Task EditFileAsync_ShouldSucceed_WhenEditAtEndOfLine() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeTrue(); - result.NewContent.Should().Be("int x = 5; // comment"); + Assert.That(result.Success, Is.True); + Assert.That(result.NewContent, Is.EqualTo("int x = 5; // comment")); } - - [Fact] + + [Test] public async Task EditFileAsync_ShouldSucceed_WhenEditEmptyLine() { // Arrange @@ -590,8 +592,8 @@ public async Task EditFileAsync_ShouldSucceed_WhenEditEmptyLine() var result = await _service.EditFileAsync("test.cs", edits); // Assert - result.Success.Should().BeTrue(); - result.NewContent.Should().Be("\ncontent"); + Assert.That(result.Success, Is.True); + Assert.That(result.NewContent, Is.EqualTo("\ncontent")); } private string CreateTestFile(string relativePath, string content) diff --git a/tests/MCPsharp.Tests/Services/IncrementalCompilationTests.cs b/tests/MCPsharp.Tests/Services/IncrementalCompilationTests.cs index 8418688..e190ca7 100644 --- a/tests/MCPsharp.Tests/Services/IncrementalCompilationTests.cs +++ b/tests/MCPsharp.Tests/Services/IncrementalCompilationTests.cs @@ -3,24 +3,22 @@ using MCPsharp.Services; using MCPsharp.Services.Roslyn; using Microsoft.CodeAnalysis; -using Xunit; -using Xunit.Abstractions; +using NUnit.Framework; namespace MCPsharp.Tests.Services; /// /// Tests for incremental compilation integration between FileOperationsService and RoslynWorkspace /// -public class IncrementalCompilationTests : IDisposable +public class IncrementalCompilationTests { - private readonly string _testRoot; - private readonly RoslynWorkspace _workspace; - private readonly FileOperationsService _fileService; - private readonly ITestOutputHelper _output; + private string _testRoot = null!; + private RoslynWorkspace _workspace = null!; + private FileOperationsService _fileService = null!; - public IncrementalCompilationTests(ITestOutputHelper output) + [SetUp] + public void SetUp() { - _output = output; _testRoot = Path.Combine(Path.GetTempPath(), $"mcpsharp-incremental-test-{Guid.NewGuid()}"); Directory.CreateDirectory(_testRoot); @@ -28,7 +26,8 @@ public IncrementalCompilationTests(ITestOutputHelper output) _fileService = new FileOperationsService(_testRoot, _workspace); } - public void Dispose() + [TearDown] + public void TearDown() { _workspace?.Dispose(); if (Directory.Exists(_testRoot)) @@ -44,7 +43,7 @@ public void Dispose() } } - [Fact] + [Test] public async Task EditFileAsync_ShouldUpdateRoslynWorkspace_WhenEditingCSharpFile() { // Arrange @@ -75,12 +74,12 @@ public void UpdatedMethod() // Verify original content is in workspace var originalDocument = _workspace.GetDocument(Path.Combine(_testRoot, testFile)); - Assert.NotNull(originalDocument); + Assert.That(originalDocument, Is.Not.Null); var originalSemanticModel = await _workspace.GetSemanticModelAsync(originalDocument!); - Assert.NotNull(originalSemanticModel); + Assert.That(originalSemanticModel, Is.Not.Null); var originalText = await originalDocument!.GetTextAsync(); - Assert.Contains("OriginalMethod", originalText.ToString()); + Assert.That(originalText.ToString(), Does.Contain("OriginalMethod")); // Act - Edit the file var edits = new List @@ -102,29 +101,29 @@ public void UpdatedMethod() var result = await _fileService.EditFileAsync(testFile, edits); // Assert - Assert.True(result.Success, $"Edit failed with error: {result.Error}"); - Assert.Equal(updatedContent.Trim(), result.NewContent?.Trim()); + Assert.That(result.Success, Is.True, $"Edit failed with error: {result.Error}"); + Assert.That(result.NewContent?.Trim(), Is.EqualTo(updatedContent.Trim())); // Verify workspace was updated with new content var updatedDocument = _workspace.GetDocument(Path.Combine(_testRoot, testFile)); - Assert.NotNull(updatedDocument); + Assert.That(updatedDocument, Is.Not.Null); var updatedSemanticModel = await _workspace.GetSemanticModelAsync(updatedDocument!); - Assert.NotNull(updatedSemanticModel); + Assert.That(updatedSemanticModel, Is.Not.Null); var updatedText = await updatedDocument!.GetTextAsync(); - Assert.Contains("UpdatedMethod", updatedText.ToString()); - Assert.Contains("Updated", updatedText.ToString()); + Assert.That(updatedText.ToString(), Does.Contain("UpdatedMethod")); + Assert.That(updatedText.ToString(), Does.Contain("Updated")); // Verify semantic model reflects the changes var root = await updatedDocument!.GetSyntaxRootAsync(); - Assert.NotNull(root); + Assert.That(root, Is.Not.Null); var methodDeclaration = root.DescendantNodes() .OfType() .FirstOrDefault(); - Assert.NotNull(methodDeclaration); - Assert.Equal("UpdatedMethod", methodDeclaration.Identifier.Text); + Assert.That(methodDeclaration, Is.Not.Null); + Assert.That(methodDeclaration.Identifier.Text, Is.EqualTo("UpdatedMethod")); } - [Fact] + [Test] public async Task WriteFileAsync_ShouldUpdateRoslynWorkspace_WhenWritingCSharpFile() { // Arrange @@ -148,29 +147,29 @@ public void NewMethod() var result = await _fileService.WriteFileAsync(testFile, content); // Assert - Assert.True(result.Success); - Assert.True(result.Created); + Assert.That(result.Success, Is.True); + Assert.That(result.Created, Is.True); // Verify workspace was updated with new file var document = _workspace.GetDocument(Path.Combine(_testRoot, testFile)); - Assert.NotNull(document); + Assert.That(document, Is.Not.Null); var semanticModel = await _workspace.GetSemanticModelAsync(document!); - Assert.NotNull(semanticModel); + Assert.That(semanticModel, Is.Not.Null); var text = await document!.GetTextAsync(); - Assert.Contains("NewClass", text.ToString()); - Assert.Contains("NewMethod", text.ToString()); + Assert.That(text.ToString(), Does.Contain("NewClass")); + Assert.That(text.ToString(), Does.Contain("NewMethod")); // Verify semantic model has correct structure var root = await document!.GetSyntaxRootAsync(); - Assert.NotNull(root); + Assert.That(root, Is.Not.Null); var classDeclaration = root.DescendantNodes() .OfType() .FirstOrDefault(); - Assert.NotNull(classDeclaration); - Assert.Equal("NewClass", classDeclaration.Identifier.Text); + Assert.That(classDeclaration, Is.Not.Null); + Assert.That(classDeclaration.Identifier.Text, Is.EqualTo("NewClass")); } - [Fact] + [Test] public async Task EditFileAsync_ShouldNotUpdateWorkspace_WhenEditingNonCSharpFile() { // Arrange @@ -185,10 +184,10 @@ public async Task EditFileAsync_ShouldNotUpdateWorkspace_WhenEditingNonCSharpFil var result = await _fileService.WriteFileAsync(testFile, updatedContent); // Assert - Assert.True(result.Success); + Assert.That(result.Success, Is.True); // Verify workspace doesn't contain the .txt file var document = _workspace.GetDocument(Path.Combine(_testRoot, testFile)); - Assert.Null(document); + Assert.That(document, Is.Null); } -} \ No newline at end of file +} diff --git a/tests/MCPsharp.Tests/Services/JsonRpcHandlerTests.cs b/tests/MCPsharp.Tests/Services/JsonRpcHandlerTests.cs index 4b62603..a04c547 100644 --- a/tests/MCPsharp.Tests/Services/JsonRpcHandlerTests.cs +++ b/tests/MCPsharp.Tests/Services/JsonRpcHandlerTests.cs @@ -1,9 +1,8 @@ using System.Text.Json; -using FluentAssertions; using MCPsharp.Models; using MCPsharp.Services; using MCPsharp.Services.Roslyn; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; @@ -19,7 +18,7 @@ public JsonRpcHandlerTests() }; } - [Fact] + [Test] public async Task HandleRequest_ShouldParseValidRequest() { // Arrange @@ -36,14 +35,14 @@ public async Task HandleRequest_ShouldParseValidRequest() var response = await handler.HandleRequest(request); // Assert - response.Should().NotBeNull(); - response.Jsonrpc.Should().Be("2.0"); - response.Id.Should().Be("test-1"); - response.Error.Should().BeNull(); - response.Result.Should().NotBeNull(); + Assert.That(response, Is.Not.Null); + Assert.That(response.Jsonrpc, Is.EqualTo("2.0")); + Assert.That(response.Id, Is.EqualTo("test-1")); + Assert.That(response.Error, Is.Null); + Assert.That(response.Result, Is.Not.Null); } - [Fact] + [Test] public async Task RunAsync_ShouldHandleInvalidJson() { // Arrange @@ -57,13 +56,13 @@ public async Task RunAsync_ShouldHandleInvalidJson() var responseLine = output.ToString().Trim(); var response = JsonSerializer.Deserialize(responseLine, _jsonOptions); - response.Should().NotBeNull(); - response!.Error.Should().NotBeNull(); - response.Error!.Code.Should().Be(JsonRpcErrorCodes.ParseError); - response.Error.Message.Should().Contain("Parse error"); + Assert.That(response, Is.Not.Null); + Assert.That(response!.Error, Is.Not.Null); + Assert.That(response.Error!.Code, Is.EqualTo(JsonRpcErrorCodes.ParseError)); + Assert.That(response.Error.Message, Does.Contain("Parse error")); } - [Fact] + [Test] public async Task HandleRequest_ShouldReturnMethodNotFoundError() { // Arrange @@ -80,13 +79,13 @@ public async Task HandleRequest_ShouldReturnMethodNotFoundError() var response = await handler.HandleRequest(request); // Assert - response.Error.Should().NotBeNull(); - response.Error!.Code.Should().Be(JsonRpcErrorCodes.MethodNotFound); - response.Error.Message.Should().Contain("Method not found"); - response.Result.Should().BeNull(); + Assert.That(response.Error, Is.Not.Null); + Assert.That(response.Error!.Code, Is.EqualTo(JsonRpcErrorCodes.MethodNotFound)); + Assert.That(response.Error.Message, Does.Contain("Method not found")); + Assert.That(response.Result, Is.Null); } - [Fact] + [Test] public async Task HandleRequest_ShouldHandleInitializeMethod() { // Arrange @@ -103,16 +102,16 @@ public async Task HandleRequest_ShouldHandleInitializeMethod() var response = await handler.HandleRequest(request); // Assert - response.Error.Should().BeNull(); - response.Result.Should().NotBeNull(); + Assert.That(response.Error, Is.Null); + Assert.That(response.Result, Is.Not.Null); var resultJson = JsonSerializer.Serialize(response.Result, _jsonOptions); - resultJson.Should().Contain("protocolVersion"); - resultJson.Should().Contain("serverInfo"); - resultJson.Should().Contain("MCPsharp"); + Assert.That(resultJson, Does.Contain("protocolVersion")); + Assert.That(resultJson, Does.Contain("serverInfo")); + Assert.That(resultJson, Does.Contain("MCPsharp")); } - [Fact] + [Test] public async Task RunAsync_ShouldMatchRequestIdInResponse() { // Arrange @@ -133,11 +132,11 @@ public async Task RunAsync_ShouldMatchRequestIdInResponse() var responseLine = output.ToString().Trim(); var response = JsonSerializer.Deserialize(responseLine, _jsonOptions); - response.Should().NotBeNull(); - response!.Id.ToString().Should().Be("unique-id-123"); + Assert.That(response, Is.Not.Null); + Assert.That(response!.Id.ToString(), Is.EqualTo("unique-id-123")); } - [Fact] + [Test] public async Task RunAsync_ShouldHandleMultipleRequests() { // Arrange @@ -158,18 +157,18 @@ public async Task RunAsync_ShouldHandleMultipleRequests() // Assert var responseLines = output.ToString().Split('\n', StringSplitOptions.RemoveEmptyEntries); - responseLines.Should().HaveCount(3); + Assert.That(responseLines, Has.Length.EqualTo(3)); var responses = responseLines .Select(line => JsonSerializer.Deserialize(line, _jsonOptions)) .ToList(); - responses[0]!.Id.ToString().Should().Be("req-1"); - responses[1]!.Id.ToString().Should().Be("req-2"); - responses[2]!.Id.ToString().Should().Be("req-3"); + Assert.That(responses[0]!.Id.ToString(), Is.EqualTo("req-1")); + Assert.That(responses[1]!.Id.ToString(), Is.EqualTo("req-2")); + Assert.That(responses[2]!.Id.ToString(), Is.EqualTo("req-3")); } - [Fact] + [Test] public async Task HandleRequest_ShouldReturnProperErrorStructure() { // Arrange @@ -186,15 +185,15 @@ public async Task HandleRequest_ShouldReturnProperErrorStructure() var response = await handler.HandleRequest(request); // Assert - response.Jsonrpc.Should().Be("2.0"); - response.Id.Should().Be("error-test"); - response.Result.Should().BeNull(); - response.Error.Should().NotBeNull(); - response.Error!.Code.Should().Be(JsonRpcErrorCodes.MethodNotFound); - response.Error.Message.Should().NotBeEmpty(); + Assert.That(response.Jsonrpc, Is.EqualTo("2.0")); + Assert.That(response.Id, Is.EqualTo("error-test")); + Assert.That(response.Result, Is.Null); + Assert.That(response.Error, Is.Not.Null); + Assert.That(response.Error!.Code, Is.EqualTo(JsonRpcErrorCodes.MethodNotFound)); + Assert.That(response.Error.Message, Is.Not.Empty); } - [Fact] + [Test] public async Task HandleRequest_ShouldRejectInvalidJsonRpcVersion() { // Arrange @@ -211,12 +210,12 @@ public async Task HandleRequest_ShouldRejectInvalidJsonRpcVersion() var response = await handler.HandleRequest(request); // Assert - response.Error.Should().NotBeNull(); - response.Error!.Code.Should().Be(JsonRpcErrorCodes.InvalidRequest); - response.Error.Message.Should().Contain("version"); + Assert.That(response.Error, Is.Not.Null); + Assert.That(response.Error!.Code, Is.EqualTo(JsonRpcErrorCodes.InvalidRequest)); + Assert.That(response.Error.Message, Does.Contain("version")); } - [Fact] + [Test] public async Task HandleRequest_ShouldHandleToolsListMethod() { // Arrange @@ -233,14 +232,14 @@ public async Task HandleRequest_ShouldHandleToolsListMethod() var response = await handler.HandleRequest(request); // Assert - response.Error.Should().BeNull(); - response.Result.Should().NotBeNull(); + Assert.That(response.Error, Is.Null); + Assert.That(response.Result, Is.Not.Null); var resultJson = JsonSerializer.Serialize(response.Result, _jsonOptions); - resultJson.Should().Contain("tools"); + Assert.That(resultJson, Does.Contain("tools")); } - [Fact] + [Test] public async Task RunAsync_ShouldSkipEmptyLines() { // Arrange @@ -254,13 +253,13 @@ public async Task RunAsync_ShouldSkipEmptyLines() // Assert var responseLines = output.ToString().Split('\n', StringSplitOptions.RemoveEmptyEntries); - responseLines.Should().HaveCount(1); + Assert.That(responseLines, Has.Length.EqualTo(1)); var response = JsonSerializer.Deserialize(responseLines[0], _jsonOptions); - response!.Id.ToString().Should().Be("skip-test"); + Assert.That(response!.Id.ToString(), Is.EqualTo("skip-test")); } - [Fact] + [Test] public async Task HandleRequest_ShouldValidateJsonRpcField() { // Arrange @@ -277,7 +276,7 @@ public async Task HandleRequest_ShouldValidateJsonRpcField() var response = await handler.HandleRequest(request); // Assert - response.Jsonrpc.Should().Be("2.0"); + Assert.That(response.Jsonrpc, Is.EqualTo("2.0")); } private static JsonRpcHandler CreateHandler(string input, out StringWriter output) diff --git a/tests/MCPsharp.Tests/Services/McpResourceRegistryTests.cs b/tests/MCPsharp.Tests/Services/McpResourceRegistryTests.cs index 43631bc..4e24c16 100644 --- a/tests/MCPsharp.Tests/Services/McpResourceRegistryTests.cs +++ b/tests/MCPsharp.Tests/Services/McpResourceRegistryTests.cs @@ -1,6 +1,6 @@ using MCPsharp.Models; using MCPsharp.Services; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; @@ -14,7 +14,7 @@ public class McpResourceRegistryTests // ===== Resource Registration Tests ===== - [Fact] + [Test] public void RegisterResource_AddsNewResource() { // Arrange @@ -34,11 +34,11 @@ public void RegisterResource_AddsNewResource() }); // Assert - Assert.True(registry.HasResource("test://resource")); - Assert.Equal(1, registry.Count); + Assert.That(registry.HasResource("test://resource"), Is.True); + Assert.That(registry.Count, Is.EqualTo(1)); } - [Fact] + [Test] public void RegisterResource_UpdatesExistingResource() { // Arrange @@ -69,13 +69,13 @@ public void RegisterResource_UpdatesExistingResource() }); // Assert - Assert.Equal(1, registry.Count); // Should still be 1, not 2 + Assert.That(registry.Count, Is.EqualTo(1)); // Should still be 1, not 2 var result = registry.ListResources(); - Assert.Single(result.Resources); - Assert.Equal("Updated Name", result.Resources[0].Name); + Assert.That(result.Resources, Has.Count.EqualTo(1)); + Assert.That(result.Resources[0].Name, Is.EqualTo("Updated Name")); } - [Fact] + [Test] public async Task RegisterResource_WithAsyncContentProvider_Works() { // Arrange @@ -99,11 +99,11 @@ public async Task RegisterResource_WithAsyncContentProvider_Works() // Assert var result = await registry.ReadResourceAsync("test://async"); - Assert.Single(result.Contents); - Assert.Equal("async content", result.Contents[0].Text); + Assert.That(result.Contents, Has.Count.EqualTo(1)); + Assert.That(result.Contents[0].Text, Is.EqualTo("async content")); } - [Fact] + [Test] public void RegisterResource_WithSyncContentProvider_Works() { // Arrange @@ -122,10 +122,10 @@ public void RegisterResource_WithSyncContentProvider_Works() }); // Assert - Assert.True(registry.HasResource("test://sync")); + Assert.That(registry.HasResource("test://sync"), Is.True); } - [Fact] + [Test] public void RegisterStaticResource_Works() { // Arrange @@ -140,10 +140,10 @@ public void RegisterStaticResource_Works() registry.RegisterStaticResource(resource, "Hello World"); // Assert - Assert.True(registry.HasResource("test://static")); + Assert.That(registry.HasResource("test://static"), Is.True); } - [Fact] + [Test] public async Task RegisterStaticResource_PreservesContent() { // Arrange @@ -159,10 +159,10 @@ public async Task RegisterStaticResource_PreservesContent() var result = await registry.ReadResourceAsync("test://static"); // Assert - Assert.Equal("Hello World", result.Contents[0].Text); + Assert.That(result.Contents[0].Text, Is.EqualTo("Hello World")); } - [Fact] + [Test] public async Task RegisterStaticResource_SetsDefaultMimeType() { // Arrange @@ -178,10 +178,10 @@ public async Task RegisterStaticResource_SetsDefaultMimeType() var result = await registry.ReadResourceAsync("test://plain"); // Assert - Assert.Equal("text/plain", result.Contents[0].MimeType); + Assert.That(result.Contents[0].MimeType, Is.EqualTo("text/plain")); } - [Fact] + [Test] public async Task RegisterStaticResource_PreservesCustomMimeType() { // Arrange @@ -198,10 +198,10 @@ public async Task RegisterStaticResource_PreservesCustomMimeType() var result = await registry.ReadResourceAsync("test://json"); // Assert - Assert.Equal("application/json", result.Contents[0].MimeType); + Assert.That(result.Contents[0].MimeType, Is.EqualTo("application/json")); } - [Fact] + [Test] public void RegisterResource_ThrowsOnNullResource() { // Arrange @@ -216,7 +216,7 @@ public void RegisterResource_ThrowsOnNullResource() })); } - [Fact] + [Test] public void RegisterResource_ThrowsOnNullAsyncContentProvider() { // Arrange @@ -233,7 +233,7 @@ public void RegisterResource_ThrowsOnNullAsyncContentProvider() registry.RegisterResource(resource, nullFunc!)); } - [Fact] + [Test] public void UnregisterResource_RemovesExistingResource() { // Arrange @@ -249,12 +249,12 @@ public void UnregisterResource_RemovesExistingResource() var removed = registry.UnregisterResource("test://resource"); // Assert - Assert.True(removed); - Assert.False(registry.HasResource("test://resource")); - Assert.Equal(0, registry.Count); + Assert.That(removed, Is.True); + Assert.That(registry.HasResource("test://resource"), Is.False); + Assert.That(registry.Count, Is.EqualTo(0)); } - [Fact] + [Test] public void UnregisterResource_ReturnsFalseForNonExistentResource() { // Arrange @@ -264,10 +264,10 @@ public void UnregisterResource_ReturnsFalseForNonExistentResource() var removed = registry.UnregisterResource("test://nonexistent"); // Assert - Assert.False(removed); + Assert.That(removed, Is.False); } - [Fact] + [Test] public void UnregisterResource_CanRemoveAndReRegister() { // Arrange @@ -284,13 +284,13 @@ public void UnregisterResource_CanRemoveAndReRegister() registry.RegisterStaticResource(resource, "new content"); // Assert - Assert.True(registry.HasResource("test://resource")); - Assert.Equal(1, registry.Count); + Assert.That(registry.HasResource("test://resource"), Is.True); + Assert.That(registry.Count, Is.EqualTo(1)); } // ===== Resource Listing Tests ===== - [Fact] + [Test] public void ListResources_ReturnsAllResources() { // Arrange @@ -307,11 +307,11 @@ public void ListResources_ReturnsAllResources() var result = registry.ListResources(); // Assert - Assert.NotNull(result.Resources); - Assert.Equal(3, result.Resources.Count); + Assert.That(result.Resources, Is.Not.Null); + Assert.That(result.Resources, Has.Count.EqualTo(3)); } - [Fact] + [Test] public void ListResources_ReturnsEmptyWhenNoResources() { // Arrange @@ -321,11 +321,11 @@ public void ListResources_ReturnsEmptyWhenNoResources() var result = registry.ListResources(); // Assert - Assert.NotNull(result.Resources); - Assert.Empty(result.Resources); + Assert.That(result.Resources, Is.Not.Null); + Assert.That(result.Resources, Is.Empty); } - [Fact] + [Test] public void ListResources_ResourcesAreSortedByUri() { // Arrange @@ -343,12 +343,12 @@ public void ListResources_ResourcesAreSortedByUri() var result = registry.ListResources(); // Assert - Assert.Equal("test://a", result.Resources[0].Uri); - Assert.Equal("test://m", result.Resources[1].Uri); - Assert.Equal("test://z", result.Resources[2].Uri); + Assert.That(result.Resources[0].Uri, Is.EqualTo("test://a")); + Assert.That(result.Resources[1].Uri, Is.EqualTo("test://m")); + Assert.That(result.Resources[2].Uri, Is.EqualTo("test://z")); } - [Fact] + [Test] public void ListResources_ContainsResourceMetadata() { // Arrange @@ -367,15 +367,15 @@ public void ListResources_ContainsResourceMetadata() // Assert var listed = result.Resources[0]; - Assert.Equal("test://resource", listed.Uri); - Assert.Equal("Test Resource", listed.Name); - Assert.Equal("A test resource", listed.Description); - Assert.Equal("text/plain", listed.MimeType); + Assert.That(listed.Uri, Is.EqualTo("test://resource")); + Assert.That(listed.Name, Is.EqualTo("Test Resource")); + Assert.That(listed.Description, Is.EqualTo("A test resource")); + Assert.That(listed.MimeType, Is.EqualTo("text/plain")); } // ===== Resource Reading Tests ===== - [Fact] + [Test] public async Task ReadResourceAsync_ReturnsContent() { // Arrange @@ -387,26 +387,26 @@ public async Task ReadResourceAsync_ReturnsContent() var result = await registry.ReadResourceAsync("test://res"); // Assert - Assert.NotNull(result.Contents); - Assert.Single(result.Contents); - Assert.Equal("Hello World", result.Contents[0].Text); + Assert.That(result.Contents, Is.Not.Null); + Assert.That(result.Contents, Has.Count.EqualTo(1)); + Assert.That(result.Contents[0].Text, Is.EqualTo("Hello World")); } - [Fact] + [Test] public async Task ReadResourceAsync_ThrowsForUnknownUri() { // Arrange var registry = CreateRegistry(); // Act & Assert - var exception = await Assert.ThrowsAsync( + var exception = Assert.ThrowsAsync( async () => await registry.ReadResourceAsync("unknown://uri")); - Assert.Contains("Resource not found", exception.Message); - Assert.Contains("unknown://uri", exception.Message); + Assert.That(exception!.Message, Does.Contain("Resource not found")); + Assert.That(exception.Message, Does.Contain("unknown://uri")); } - [Fact] + [Test] public async Task ReadResourceAsync_ContentProviderIsInvokedEachTime() { // Arrange @@ -425,11 +425,11 @@ public async Task ReadResourceAsync_ContentProviderIsInvokedEachTime() var result2 = await registry.ReadResourceAsync("test://counter"); // Assert - Assert.Equal("Count: 1", result1.Contents[0].Text); - Assert.Equal("Count: 2", result2.Contents[0].Text); + Assert.That(result1.Contents[0].Text, Is.EqualTo("Count: 1")); + Assert.That(result2.Contents[0].Text, Is.EqualTo("Count: 2")); } - [Fact] + [Test] public async Task ReadResourceAsync_PreservesContentUri() { // Arrange @@ -441,10 +441,10 @@ public async Task ReadResourceAsync_PreservesContentUri() var result = await registry.ReadResourceAsync("test://res"); // Assert - Assert.Equal("test://res", result.Contents[0].Uri); + Assert.That(result.Contents[0].Uri, Is.EqualTo("test://res")); } - [Fact] + [Test] public async Task ReadResourceAsync_SupportsTextContent() { // Arrange @@ -461,11 +461,11 @@ public async Task ReadResourceAsync_SupportsTextContent() var result = await registry.ReadResourceAsync("test://text"); // Assert - Assert.Equal("text content", result.Contents[0].Text); - Assert.Null(result.Contents[0].Blob); + Assert.That(result.Contents[0].Text, Is.EqualTo("text content")); + Assert.That(result.Contents[0].Blob, Is.Null); } - [Fact] + [Test] public async Task ReadResourceAsync_SupportsBlobContent() { // Arrange @@ -484,13 +484,13 @@ public async Task ReadResourceAsync_SupportsBlobContent() var result = await registry.ReadResourceAsync("test://blob"); // Assert - Assert.Equal(base64Data, result.Contents[0].Blob); - Assert.Null(result.Contents[0].Text); + Assert.That(result.Contents[0].Blob, Is.EqualTo(base64Data)); + Assert.That(result.Contents[0].Text, Is.Null); } // ===== Utility Methods Tests ===== - [Fact] + [Test] public void HasResource_ReturnsTrueForExistingResource() { // Arrange @@ -502,10 +502,10 @@ public void HasResource_ReturnsTrueForExistingResource() var exists = registry.HasResource("test://exists"); // Assert - Assert.True(exists); + Assert.That(exists, Is.True); } - [Fact] + [Test] public void HasResource_ReturnsFalseForNonExistentResource() { // Arrange @@ -515,10 +515,10 @@ public void HasResource_ReturnsFalseForNonExistentResource() var exists = registry.HasResource("test://nonexistent"); // Assert - Assert.False(exists); + Assert.That(exists, Is.False); } - [Fact] + [Test] public void HasResource_ReturnsFalseAfterUnregister() { // Arrange @@ -531,38 +531,38 @@ public void HasResource_ReturnsFalseAfterUnregister() var exists = registry.HasResource("test://temp"); // Assert - Assert.False(exists); + Assert.That(exists, Is.False); } - [Fact] + [Test] public void Count_IsAccurate() { // Arrange var registry = CreateRegistry(); // Act & Assert - empty - Assert.Equal(0, registry.Count); + Assert.That(registry.Count, Is.EqualTo(0)); // Add resources registry.RegisterStaticResource(new McpResource { Uri = "test://1", Name = "1" }, "1"); - Assert.Equal(1, registry.Count); + Assert.That(registry.Count, Is.EqualTo(1)); registry.RegisterStaticResource(new McpResource { Uri = "test://2", Name = "2" }, "2"); - Assert.Equal(2, registry.Count); + Assert.That(registry.Count, Is.EqualTo(2)); registry.RegisterStaticResource(new McpResource { Uri = "test://3", Name = "3" }, "3"); - Assert.Equal(3, registry.Count); + Assert.That(registry.Count, Is.EqualTo(3)); // Update existing (count should not change) registry.RegisterStaticResource(new McpResource { Uri = "test://1", Name = "Updated" }, "updated"); - Assert.Equal(3, registry.Count); + Assert.That(registry.Count, Is.EqualTo(3)); // Remove resource registry.UnregisterResource("test://2"); - Assert.Equal(2, registry.Count); + Assert.That(registry.Count, Is.EqualTo(2)); } - [Fact] + [Test] public void Clear_RemovesAllResources() { // Arrange @@ -575,14 +575,14 @@ public void Clear_RemovesAllResources() registry.Clear(); // Assert - Assert.Equal(0, registry.Count); - Assert.False(registry.HasResource("test://1")); - Assert.False(registry.HasResource("test://2")); - Assert.False(registry.HasResource("test://3")); - Assert.Empty(registry.ListResources().Resources); + Assert.That(registry.Count, Is.EqualTo(0)); + Assert.That(registry.HasResource("test://1"), Is.False); + Assert.That(registry.HasResource("test://2"), Is.False); + Assert.That(registry.HasResource("test://3"), Is.False); + Assert.That(registry.ListResources().Resources, Is.Empty); } - [Fact] + [Test] public void Clear_OnEmptyRegistry_DoesNotThrow() { // Arrange @@ -590,12 +590,12 @@ public void Clear_OnEmptyRegistry_DoesNotThrow() // Act & Assert registry.Clear(); - Assert.Equal(0, registry.Count); + Assert.That(registry.Count, Is.EqualTo(0)); } // ===== Edge Case Tests ===== - [Fact] + [Test] public async Task RegisterResource_WithEmptyContent_Works() { // Arrange @@ -607,10 +607,10 @@ public async Task RegisterResource_WithEmptyContent_Works() var result = await registry.ReadResourceAsync("test://empty"); // Assert - Assert.Equal("", result.Contents[0].Text); + Assert.That(result.Contents[0].Text, Is.EqualTo("")); } - [Fact] + [Test] public async Task RegisterResource_WithVeryLongContent_Works() { // Arrange @@ -623,10 +623,10 @@ public async Task RegisterResource_WithVeryLongContent_Works() var result = await registry.ReadResourceAsync("test://long"); // Assert - Assert.Equal(longContent, result.Contents[0].Text); + Assert.That(result.Contents[0].Text, Is.EqualTo(longContent)); } - [Fact] + [Test] public void RegisterResource_WithSpecialCharactersInUri_Works() { // Arrange @@ -641,10 +641,10 @@ public void RegisterResource_WithSpecialCharactersInUri_Works() registry.RegisterStaticResource(resource, "content"); // Assert - Assert.True(registry.HasResource("test://resource-with-dashes_and_underscores/path?query=value#fragment")); + Assert.That(registry.HasResource("test://resource-with-dashes_and_underscores/path?query=value#fragment"), Is.True); } - [Fact] + [Test] public async Task RegisterResource_WithContentProviderException_ThrowsOnRead() { // Arrange @@ -655,13 +655,13 @@ public async Task RegisterResource_WithContentProviderException_ThrowsOnRead() new InvalidOperationException("Content provider failed"))); // Act & Assert - var exception = await Assert.ThrowsAsync( + var exception = Assert.ThrowsAsync( async () => await registry.ReadResourceAsync("test://error")); - Assert.Equal("Content provider failed", exception.Message); + Assert.That(exception!.Message, Is.EqualTo("Content provider failed")); } - [Fact] + [Test] public async Task RegisterResource_ConcurrentRegistration_ThreadSafe() { // Arrange @@ -686,14 +686,14 @@ public async Task RegisterResource_ConcurrentRegistration_ThreadSafe() await Task.WhenAll(tasks); // Assert - Assert.Equal(100, registry.Count); + Assert.That(registry.Count, Is.EqualTo(100)); for (int i = 0; i < 100; i++) { - Assert.True(registry.HasResource($"test://concurrent{i}")); + Assert.That(registry.HasResource($"test://concurrent{i}"), Is.True); } } - [Fact] + [Test] public async Task RegisterResource_ConcurrentReadAndWrite_ThreadSafe() { // Arrange @@ -734,11 +734,22 @@ public async Task RegisterResource_ConcurrentReadAndWrite_ThreadSafe() } // Assert - Should complete without exceptions - var aggregateException = await Record.ExceptionAsync(async () => await Task.WhenAll(tasks)); - Assert.Null(aggregateException); + var exception = await Task.Run(async () => + { + try + { + await Task.WhenAll(tasks); + return null; + } + catch (Exception ex) + { + return ex; + } + }); + Assert.That(exception, Is.Null); } - [Fact] + [Test] public void ListResources_WithManyResources_PerformanceTest() { // Arrange @@ -759,7 +770,7 @@ public void ListResources_WithManyResources_PerformanceTest() sw.Stop(); // Assert - Assert.Equal(1000, result.Resources.Count); - Assert.True(sw.ElapsedMilliseconds < 1000, $"ListResources took {sw.ElapsedMilliseconds}ms (expected < 1000ms)"); + Assert.That(result.Resources.Count, Is.EqualTo(1000)); + Assert.That(sw.ElapsedMilliseconds, Is.LessThan(1000), $"ListResources took {sw.ElapsedMilliseconds}ms (expected < 1000ms)"); } } diff --git a/tests/MCPsharp.Tests/Services/McpToolRegistryTests.cs b/tests/MCPsharp.Tests/Services/McpToolRegistryTests.cs index 72a2a79..5bbb0e1 100644 --- a/tests/MCPsharp.Tests/Services/McpToolRegistryTests.cs +++ b/tests/MCPsharp.Tests/Services/McpToolRegistryTests.cs @@ -1,17 +1,18 @@ using System.Text.Json; using MCPsharp.Models; using MCPsharp.Services; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; -public class McpToolRegistryTests : IDisposable +public class McpToolRegistryTests { - private readonly string _testProjectPath; - private readonly ProjectContextManager _projectContext; - private readonly McpToolRegistry _registry; + private string _testProjectPath = null!; + private ProjectContextManager _projectContext = null!; + private McpToolRegistry _registry = null!; - public McpToolRegistryTests() + [SetUp] + public void SetUp() { // Create a temporary test directory _testProjectPath = Path.Combine(Path.GetTempPath(), $"mcpsharp_test_{Guid.NewGuid()}"); @@ -21,7 +22,8 @@ public McpToolRegistryTests() _registry = new McpToolRegistry(_projectContext); } - public void Dispose() + [TearDown] + public void TearDown() { // Clean up test directory if (Directory.Exists(_testProjectPath)) @@ -30,69 +32,69 @@ public void Dispose() } } - [Fact] + [Test] public void GetTools_ReturnsAllThirtySevenTools() { // Act var tools = _registry.GetTools(); // Assert - Assert.NotNull(tools); - Assert.Equal(37, tools.Count); + Assert.That(tools, Is.Not.Null); + Assert.That(tools.Count, Is.EqualTo(37)); var toolNames = tools.Select(t => t.Name).ToList(); // Phase 0 tools (7) - Assert.Contains("project_open", toolNames); - Assert.Contains("project_info", toolNames); - Assert.Contains("file_list", toolNames); - Assert.Contains("file_read", toolNames); - Assert.Contains("file_write", toolNames); - Assert.Contains("file_edit", toolNames); - Assert.Contains("search_text", toolNames); + Assert.That(toolNames, Does.Contain("project_open")); + Assert.That(toolNames, Does.Contain("project_info")); + Assert.That(toolNames, Does.Contain("file_list")); + Assert.That(toolNames, Does.Contain("file_read")); + Assert.That(toolNames, Does.Contain("file_write")); + Assert.That(toolNames, Does.Contain("file_edit")); + Assert.That(toolNames, Does.Contain("search_text")); // Phase 1 tools (8) - Assert.Contains("find_symbol", toolNames); - Assert.Contains("get_symbol_info", toolNames); - Assert.Contains("get_class_structure", toolNames); - Assert.Contains("add_class_property", toolNames); - Assert.Contains("add_class_method", toolNames); - Assert.Contains("find_references", toolNames); - Assert.Contains("find_implementations", toolNames); - Assert.Contains("parse_project", toolNames); + Assert.That(toolNames, Does.Contain("find_symbol")); + Assert.That(toolNames, Does.Contain("get_symbol_info")); + Assert.That(toolNames, Does.Contain("get_class_structure")); + Assert.That(toolNames, Does.Contain("add_class_property")); + Assert.That(toolNames, Does.Contain("add_class_method")); + Assert.That(toolNames, Does.Contain("find_references")); + Assert.That(toolNames, Does.Contain("find_implementations")); + Assert.That(toolNames, Does.Contain("parse_project")); // Phase 2 tools (7) - Assert.Contains("get_workflows", toolNames); - Assert.Contains("parse_workflow", toolNames); - Assert.Contains("validate_workflow_consistency", toolNames); - Assert.Contains("get_config_schema", toolNames); - Assert.Contains("merge_configs", toolNames); - Assert.Contains("analyze_impact", toolNames); - Assert.Contains("trace_feature", toolNames); + Assert.That(toolNames, Does.Contain("get_workflows")); + Assert.That(toolNames, Does.Contain("parse_workflow")); + Assert.That(toolNames, Does.Contain("validate_workflow_consistency")); + Assert.That(toolNames, Does.Contain("get_config_schema")); + Assert.That(toolNames, Does.Contain("merge_configs")); + Assert.That(toolNames, Does.Contain("analyze_impact")); + Assert.That(toolNames, Does.Contain("trace_feature")); // Advanced analysis tools (10) - Assert.Contains("find_callers", toolNames); - Assert.Contains("find_call_chains", toolNames); - Assert.Contains("find_type_usages", toolNames); - Assert.Contains("analyze_call_patterns", toolNames); - Assert.Contains("analyze_inheritance", toolNames); - Assert.Contains("find_circular_dependencies", toolNames); - Assert.Contains("find_unused_methods", toolNames); - Assert.Contains("analyze_call_graph", toolNames); - Assert.Contains("find_recursive_calls", toolNames); - Assert.Contains("analyze_type_dependencies", toolNames); - Assert.Contains("rename_symbol", toolNames); + Assert.That(toolNames, Does.Contain("find_callers")); + Assert.That(toolNames, Does.Contain("find_call_chains")); + Assert.That(toolNames, Does.Contain("find_type_usages")); + Assert.That(toolNames, Does.Contain("analyze_call_patterns")); + Assert.That(toolNames, Does.Contain("analyze_inheritance")); + Assert.That(toolNames, Does.Contain("find_circular_dependencies")); + Assert.That(toolNames, Does.Contain("find_unused_methods")); + Assert.That(toolNames, Does.Contain("analyze_call_graph")); + Assert.That(toolNames, Does.Contain("find_recursive_calls")); + Assert.That(toolNames, Does.Contain("analyze_type_dependencies")); + Assert.That(toolNames, Does.Contain("rename_symbol")); // Code quality tools (3) - Assert.Contains("code_quality_analyze", toolNames); - Assert.Contains("code_quality_fix", toolNames); - Assert.Contains("code_quality_profiles", toolNames); + Assert.That(toolNames, Does.Contain("code_quality_analyze")); + Assert.That(toolNames, Does.Contain("code_quality_fix")); + Assert.That(toolNames, Does.Contain("code_quality_profiles")); // Refactoring tools (1) - Assert.Contains("extract_method", toolNames); + Assert.That(toolNames, Does.Contain("extract_method")); } - [Fact] + [Test] public void GetTools_EachToolHasValidNameDescriptionAndSchema() { // Act @@ -101,21 +103,21 @@ public void GetTools_EachToolHasValidNameDescriptionAndSchema() // Assert foreach (var tool in tools) { - Assert.NotNull(tool.Name); - Assert.NotEmpty(tool.Name); - Assert.NotNull(tool.Description); - Assert.NotEmpty(tool.Description); - Assert.NotNull(tool.InputSchema); + Assert.That(tool.Name, Is.Not.Null); + Assert.That(tool.Name, Is.Not.Empty); + Assert.That(tool.Description, Is.Not.Null); + Assert.That(tool.Description, Is.Not.Empty); + Assert.That(tool.InputSchema, Is.Not.Null); // Verify schema is valid JSON var schemaRoot = tool.InputSchema.RootElement; - Assert.Equal(JsonValueKind.Object, schemaRoot.ValueKind); - Assert.True(schemaRoot.TryGetProperty("type", out var typeProperty)); - Assert.Equal("object", typeProperty.GetString()); + Assert.That(schemaRoot.ValueKind, Is.EqualTo(JsonValueKind.Object)); + Assert.That(schemaRoot.TryGetProperty("type", out var typeProperty), Is.True); + Assert.That(typeProperty.GetString(), Is.EqualTo("object")); } } - [Fact] + [Test] public async Task ExecuteTool_ProjectOpen_WithValidPath_Succeeds() { // Arrange @@ -129,12 +131,12 @@ public async Task ExecuteTool_ProjectOpen_WithValidPath_Succeeds() var result = await _registry.ExecuteTool(request); // Assert - Assert.True(result.Success); - Assert.Null(result.Error); - Assert.NotNull(result.Result); + Assert.That(result.Success, Is.True); + Assert.That(result.Error, Is.Null); + Assert.That(result.Result, Is.Not.Null); } - [Fact] + [Test] public async Task ExecuteTool_ProjectOpen_WithInvalidPath_Fails() { // Arrange @@ -149,12 +151,12 @@ public async Task ExecuteTool_ProjectOpen_WithInvalidPath_Fails() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("not exist", result.Error, StringComparison.OrdinalIgnoreCase); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("not exist").IgnoreCase); } - [Fact] + [Test] public async Task ExecuteTool_ProjectInfo_WithoutOpenProject_Fails() { // Arrange @@ -168,12 +170,12 @@ public async Task ExecuteTool_ProjectInfo_WithoutOpenProject_Fails() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("No project", result.Error, StringComparison.OrdinalIgnoreCase); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("No project").IgnoreCase); } - [Fact] + [Test] public async Task ExecuteTool_ProjectInfo_WithOpenProject_Succeeds() { // Arrange @@ -188,12 +190,12 @@ public async Task ExecuteTool_ProjectInfo_WithOpenProject_Succeeds() var result = await _registry.ExecuteTool(request); // Assert - Assert.True(result.Success); - Assert.Null(result.Error); - Assert.NotNull(result.Result); + Assert.That(result.Success, Is.True); + Assert.That(result.Error, Is.Null); + Assert.That(result.Result, Is.Not.Null); } - [Fact] + [Test] public async Task ExecuteTool_FileList_ReturnsFiles() { // Arrange @@ -220,11 +222,11 @@ await _registry.ExecuteTool(new ToolCallRequest var result = await _registry.ExecuteTool(request); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); } - [Fact] + [Test] public async Task ExecuteTool_FileList_WithPattern_FiltersFiles() { // Arrange @@ -249,11 +251,11 @@ await _registry.ExecuteTool(new ToolCallRequest var result = await _registry.ExecuteTool(request); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); } - [Fact] + [Test] public async Task ExecuteTool_FileRead_ReturnsContent() { // Arrange @@ -278,11 +280,11 @@ await _registry.ExecuteTool(new ToolCallRequest var result = await _registry.ExecuteTool(request); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); } - [Fact] + [Test] public async Task ExecuteTool_FileRead_NonExistentFile_Fails() { // Arrange @@ -303,11 +305,11 @@ await _registry.ExecuteTool(new ToolCallRequest var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); } - [Fact] + [Test] public async Task ExecuteTool_FileWrite_CreatesFile() { // Arrange @@ -329,16 +331,16 @@ await _registry.ExecuteTool(new ToolCallRequest var result = await _registry.ExecuteTool(request); // Assert - Assert.True(result.Success); - Assert.Null(result.Error); + Assert.That(result.Success, Is.True); + Assert.That(result.Error, Is.Null); var filePath = Path.Combine(_testProjectPath, "newfile.txt"); - Assert.True(File.Exists(filePath)); + Assert.That(File.Exists(filePath), Is.True); var actualContent = await File.ReadAllTextAsync(filePath); - Assert.Equal(content, actualContent); + Assert.That(actualContent, Is.EqualTo(content)); } - [Fact] + [Test] public async Task ExecuteTool_FileWrite_OverwritesExistingFile() { // Arrange @@ -363,12 +365,12 @@ await _registry.ExecuteTool(new ToolCallRequest var result = await _registry.ExecuteTool(request); // Assert - Assert.True(result.Success); + Assert.That(result.Success, Is.True); var actualContent = await File.ReadAllTextAsync(filePath); - Assert.Equal(newContent, actualContent); + Assert.That(actualContent, Is.EqualTo(newContent)); } - [Fact] + [Test] public async Task ExecuteTool_FileEdit_AppliesEdits() { // Arrange @@ -406,11 +408,11 @@ await _registry.ExecuteTool(new ToolCallRequest var result = await _registry.ExecuteTool(request); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); } - [Fact] + [Test] public async Task ExecuteTool_UnknownTool_ReturnsError() { // Arrange @@ -424,12 +426,12 @@ public async Task ExecuteTool_UnknownTool_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Unknown tool", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Unknown tool")); } - [Fact] + [Test] public async Task ExecuteTool_InvalidArguments_ReturnsError() { // Arrange @@ -443,13 +445,13 @@ public async Task ExecuteTool_InvalidArguments_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); } // ===== Phase 1 Tool Tests ===== - [Fact] + [Test] public async Task ExecuteTool_FindSymbol_WithoutWorkspace_ReturnsError() { // Arrange @@ -463,12 +465,12 @@ public async Task ExecuteTool_FindSymbol_WithoutWorkspace_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Workspace not initialized", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Workspace not initialized")); } - [Fact] + [Test] public async Task ExecuteTool_GetSymbolInfo_WithoutWorkspace_ReturnsError() { // Arrange @@ -482,12 +484,12 @@ public async Task ExecuteTool_GetSymbolInfo_WithoutWorkspace_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Workspace not initialized", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Workspace not initialized")); } - [Fact] + [Test] public async Task ExecuteTool_GetClassStructure_WithoutWorkspace_ReturnsError() { // Arrange @@ -501,12 +503,12 @@ public async Task ExecuteTool_GetClassStructure_WithoutWorkspace_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Workspace not initialized", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Workspace not initialized")); } - [Fact] + [Test] public async Task ExecuteTool_AddClassProperty_WithoutWorkspace_ReturnsError() { // Arrange @@ -520,12 +522,12 @@ public async Task ExecuteTool_AddClassProperty_WithoutWorkspace_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Workspace not initialized", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Workspace not initialized")); } - [Fact] + [Test] public async Task ExecuteTool_AddClassMethod_WithoutWorkspace_ReturnsError() { // Arrange @@ -539,12 +541,12 @@ public async Task ExecuteTool_AddClassMethod_WithoutWorkspace_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Workspace not initialized", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Workspace not initialized")); } - [Fact] + [Test] public async Task ExecuteTool_FindReferences_WithoutWorkspace_ReturnsError() { // Arrange @@ -558,12 +560,12 @@ public async Task ExecuteTool_FindReferences_WithoutWorkspace_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Workspace not initialized", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Workspace not initialized")); } - [Fact] + [Test] public async Task ExecuteTool_FindImplementations_WithoutWorkspace_ReturnsError() { // Arrange @@ -577,12 +579,12 @@ public async Task ExecuteTool_FindImplementations_WithoutWorkspace_ReturnsError( var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Workspace not initialized", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Workspace not initialized")); } - [Fact] + [Test] public async Task ExecuteTool_ParseProject_WithValidProject_Succeeds() { // Arrange @@ -605,13 +607,13 @@ public async Task ExecuteTool_ParseProject_WithValidProject_Succeeds() var result = await _registry.ExecuteTool(request); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Result); + Assert.That(result.Success, Is.True); + Assert.That(result.Result, Is.Not.Null); } // ===== Phase 2 Tool Tests ===== - [Fact] + [Test] public async Task ExecuteTool_GetWorkflows_WithoutService_ReturnsError() { // Arrange @@ -625,12 +627,12 @@ public async Task ExecuteTool_GetWorkflows_WithoutService_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Phase 2 features", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Phase 2 features")); } - [Fact] + [Test] public async Task ExecuteTool_ParseWorkflow_WithoutService_ReturnsError() { // Arrange @@ -644,12 +646,12 @@ public async Task ExecuteTool_ParseWorkflow_WithoutService_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Phase 2 features", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Phase 2 features")); } - [Fact] + [Test] public async Task ExecuteTool_ValidateWorkflowConsistency_WithoutService_ReturnsError() { // Arrange @@ -663,12 +665,12 @@ public async Task ExecuteTool_ValidateWorkflowConsistency_WithoutService_Returns var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Phase 2 features", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Phase 2 features")); } - [Fact] + [Test] public async Task ExecuteTool_GetConfigSchema_WithoutService_ReturnsError() { // Arrange @@ -682,12 +684,12 @@ public async Task ExecuteTool_GetConfigSchema_WithoutService_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Phase 2 features", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Phase 2 features")); } - [Fact] + [Test] public async Task ExecuteTool_MergeConfigs_WithoutService_ReturnsError() { // Arrange @@ -701,12 +703,12 @@ public async Task ExecuteTool_MergeConfigs_WithoutService_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Phase 2 features", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Phase 2 features")); } - [Fact] + [Test] public async Task ExecuteTool_AnalyzeImpact_WithoutService_ReturnsError() { // Arrange @@ -720,12 +722,12 @@ public async Task ExecuteTool_AnalyzeImpact_WithoutService_ReturnsError() var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Phase 2 features", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Phase 2 features")); } - [Fact] + [Test] public async Task ExecuteTool_TraceFeature_WithFeatureName_WithoutService_ReturnsError() { // Arrange @@ -739,12 +741,12 @@ public async Task ExecuteTool_TraceFeature_WithFeatureName_WithoutService_Return var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Phase 2 features", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Phase 2 features")); } - [Fact] + [Test] public async Task ExecuteTool_TraceFeature_WithEntryPoint_WithoutService_ReturnsError() { // Arrange @@ -758,8 +760,8 @@ public async Task ExecuteTool_TraceFeature_WithEntryPoint_WithoutService_Returns var result = await _registry.ExecuteTool(request); // Assert - Assert.False(result.Success); - Assert.NotNull(result.Error); - Assert.Contains("Phase 2 features", result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); + Assert.That(result.Error, Does.Contain("Phase 2 features")); } } diff --git a/tests/MCPsharp.Tests/Services/Phase3/SqlMigrationAnalyzerServiceTests.cs b/tests/MCPsharp.Tests/Services/Phase3/SqlMigrationAnalyzerServiceTests.cs index 69e3e9f..a6b6d64 100644 --- a/tests/MCPsharp.Tests/Services/Phase3/SqlMigrationAnalyzerServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/Phase3/SqlMigrationAnalyzerServiceTests.cs @@ -1,7 +1,6 @@ using Microsoft.Extensions.Logging; using NSubstitute; -using Xunit; -using FluentAssertions; +using NUnit.Framework; using MCPsharp.Models.SqlMigration; using MCPsharp.Services.Phase3; @@ -24,7 +23,7 @@ public SqlMigrationAnalyzerServiceTests() _service = new SqlMigrationAnalyzerService(_mockLogger, _mockLoggerFactory); } - [Fact] + [Test] public async Task DetectDatabaseProvider_ShouldReturnSqlServer_WhenSqlServerPackageExists() { // Arrange @@ -42,13 +41,13 @@ await File.WriteAllTextAsync(csprojPath, @" var result = await _service.DetectDatabaseProviderAsync(tempDir); // Assert - result.Should().Be(DatabaseProvider.SqlServer); + Assert.That(result, Is.EqualTo(DatabaseProvider.SqlServer)); // Cleanup Directory.Delete(tempDir, true); } - [Fact] + [Test] public async Task GetMigrationFiles_ShouldReturnEmptyList_WhenNoMigrationsExist() { // Arrange @@ -58,24 +57,24 @@ public async Task GetMigrationFiles_ShouldReturnEmptyList_WhenNoMigrationsExist( var result = await _service.GetMigrationFilesAsync(tempDir); // Assert - result.Should().BeEmpty(); + Assert.That(result, Is.Empty); // Cleanup Directory.Delete(tempDir, true); } - [Fact] + [Test] public async Task ParseMigrationFile_ShouldThrowFileNotFoundException_WhenFileDoesNotExist() { // Arrange var nonExistentFile = Path.Combine(Path.GetTempPath(), "nonexistent.cs"); // Act & Assert - await Assert.ThrowsAsync( - () => _service.ParseMigrationFileAsync(nonExistentFile)); + Assert.ThrowsAsync(async () => + await _service.ParseMigrationFileAsync(nonExistentFile)); } - [Fact] + [Test] public async Task GenerateMigrationReport_ShouldReturnValidReport_WhenProjectIsValid() { // Arrange @@ -85,17 +84,17 @@ public async Task GenerateMigrationReport_ShouldReturnValidReport_WhenProjectIsV var result = await _service.GenerateMigrationReportAsync(tempDir, false); // Assert - result.Should().NotBeNull(); - result.Metadata.Should().NotBeNull(); - result.Metadata.ProjectPath.Should().Be(tempDir); - result.Metadata.GeneratedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromMinutes(1)); - result.Metadata.TotalMigrations.Should().Be(0); + Assert.That(result, Is.Not.Null); + Assert.That(result.Metadata, Is.Not.Null); + Assert.That(result.Metadata.ProjectPath, Is.EqualTo(tempDir)); + Assert.That(result.Metadata.GeneratedAt, Is.EqualTo(DateTime.UtcNow).Within(TimeSpan.FromMinutes(1))); + Assert.That(result.Metadata.TotalMigrations, Is.EqualTo(0)); // Cleanup Directory.Delete(tempDir, true); } - [Fact] + [Test] public async Task ValidateMigrations_ShouldReturnEmptyList_WhenNoMigrationsExist() { // Arrange @@ -105,13 +104,13 @@ public async Task ValidateMigrations_ShouldReturnEmptyList_WhenNoMigrationsExist var result = await _service.ValidateMigrationsAsync(tempDir); // Assert - result.Should().BeEmpty(); + Assert.That(result, Is.Empty); // Cleanup Directory.Delete(tempDir, true); } - [Fact] + [Test] public async Task EstimateMigrationExecution_ShouldReturnValidEstimate_ForValidInputs() { // Arrange @@ -121,15 +120,15 @@ public async Task EstimateMigrationExecution_ShouldReturnValidEstimate_ForValidI var result = await _service.EstimateMigrationExecutionAsync("TestMigration", tempDir); // Assert - result.Should().NotBeNull(); - result.MigrationName.Should().Be("TestMigration"); - result.EstimatedExecutionTime.Should().BeGreaterOrEqualTo(TimeSpan.Zero); + Assert.That(result, Is.Not.Null); + Assert.That(result.MigrationName, Is.EqualTo("TestMigration")); + Assert.That(result.EstimatedExecutionTime, Is.GreaterThanOrEqualTo(TimeSpan.Zero)); // Cleanup Directory.Delete(tempDir, true); } - [Fact] + [Test] public async Task AnalyzeMigrations_ShouldReturnValidAnalysis_WhenProjectIsValid() { // Arrange @@ -139,19 +138,19 @@ public async Task AnalyzeMigrations_ShouldReturnValidAnalysis_WhenProjectIsValid var result = await _service.AnalyzeMigrationsAsync(tempDir); // Assert - result.Should().NotBeNull(); - result.Summary.Should().NotBeNull(); - result.Summary.TotalMigrations.Should().Be(0); - result.Summary.AppliedMigrations.Should().Be(0); - result.Summary.PendingMigrations.Should().Be(0); - result.Migrations.Should().BeEmpty(); - result.BreakingChanges.Should().BeEmpty(); + Assert.That(result, Is.Not.Null); + Assert.That(result.Summary, Is.Not.Null); + Assert.That(result.Summary.TotalMigrations, Is.EqualTo(0)); + Assert.That(result.Summary.AppliedMigrations, Is.EqualTo(0)); + Assert.That(result.Summary.PendingMigrations, Is.EqualTo(0)); + Assert.That(result.Migrations, Is.Empty); + Assert.That(result.BreakingChanges, Is.Empty); // Cleanup Directory.Delete(tempDir, true); } - [Fact] + [Test] public async Task TrackSchemaEvolution_ShouldReturnEmptyEvolution_WhenNoMigrationsExist() { // Arrange @@ -161,16 +160,16 @@ public async Task TrackSchemaEvolution_ShouldReturnEmptyEvolution_WhenNoMigratio var result = await _service.TrackSchemaEvolutionAsync(tempDir); // Assert - result.Should().NotBeNull(); - result.Snapshots.Should().BeEmpty(); - result.Changes.Should().BeEmpty(); - result.Metrics.Should().BeEmpty(); + Assert.That(result, Is.Not.Null); + Assert.That(result.Snapshots, Is.Empty); + Assert.That(result.Changes, Is.Empty); + Assert.That(result.Metrics, Is.Empty); // Cleanup Directory.Delete(tempDir, true); } - [Fact] + [Test] public async Task DetectBreakingChanges_ShouldReturnEmptyList_WhenMigrationsNotFound() { // Arrange @@ -180,13 +179,13 @@ public async Task DetectBreakingChanges_ShouldReturnEmptyList_WhenMigrationsNotF var result = await _service.DetectBreakingChangesAsync("NonExistent1", "NonExistent2", tempDir); // Assert - result.Should().BeEmpty(); + Assert.That(result, Is.Empty); // Cleanup Directory.Delete(tempDir, true); } - [Fact] + [Test] public async Task GetMigrationDependencies_ShouldReturnValidDependency_ForValidInputs() { // Arrange @@ -196,16 +195,16 @@ public async Task GetMigrationDependencies_ShouldReturnValidDependency_ForValidI var result = await _service.GetMigrationDependenciesAsync("TestMigration", tempDir); // Assert - result.Should().NotBeNull(); - result.MigrationName.Should().Be("TestMigration"); - result.DependsOn.Should().BeEmpty(); - result.RequiredBy.Should().BeEmpty(); + Assert.That(result, Is.Not.Null); + Assert.That(result.MigrationName, Is.EqualTo("TestMigration")); + Assert.That(result.DependsOn, Is.Empty); + Assert.That(result.RequiredBy, Is.Empty); // Cleanup Directory.Delete(tempDir, true); } - [Fact] + [Test] public async Task GetMigrationHistory_ShouldReturnEmptyList_WhenDbContextDoesNotExist() { // Arrange @@ -215,7 +214,7 @@ public async Task GetMigrationHistory_ShouldReturnEmptyList_WhenDbContextDoesNot var result = await _service.GetMigrationHistoryAsync(nonExistentDbContext); // Assert - result.Should().BeEmpty(); + Assert.That(result, Is.Empty); } private string CreateTempProjectDirectory() @@ -278,7 +277,7 @@ protected override void Down(MigrationBuilder migrationBuilder) return migrationPath; } - [Fact] + [Test] public async Task ParseMigrationFile_ShouldReturnValidMigrationInfo_ForValidMigrationFile() { // Arrange @@ -289,17 +288,17 @@ public async Task ParseMigrationFile_ShouldReturnValidMigrationInfo_ForValidMigr var result = await _service.ParseMigrationFileAsync(migrationPath); // Assert - result.Should().NotBeNull(); - result.Name.Should().Be("CreateTestTable"); - result.FilePath.Should().Be(migrationPath); - result.Operations.Should().NotBeEmpty(); - result.Operations.Should().Contain(o => o.Type.Equals("CreateTable", StringComparison.OrdinalIgnoreCase)); + Assert.That(result, Is.Not.Null); + Assert.That(result.Name, Is.EqualTo("CreateTestTable")); + Assert.That(result.FilePath, Is.EqualTo(migrationPath)); + Assert.That(result.Operations, Is.Not.Empty); + Assert.That(result.Operations, Has.Some.Matches(o => o.Type.Equals("CreateTable", StringComparison.OrdinalIgnoreCase))); // Cleanup Directory.Delete(tempDir, true); } - [Fact] + [Test] public async Task AnalyzeMigrations_ShouldDetectMigrations_WhenMigrationsExist() { // Arrange @@ -311,13 +310,19 @@ public async Task AnalyzeMigrations_ShouldDetectMigrations_WhenMigrationsExist() var result = await _service.AnalyzeMigrationsAsync(tempDir); // Assert - result.Should().NotBeNull(); - result.Summary.TotalMigrations.Should().Be(2); - result.Migrations.Should().HaveCount(2); - result.Migrations.Should().Contain(m => m.Name == "CreateTestTable"); - result.Migrations.Should().Contain(m => m.Name == "AddColumnToTestTable"); + Assert.That(result, Is.Not.Null); + Assert.That(result.Summary.TotalMigrations, Is.EqualTo(2)); + Assert.That(result.Migrations, Has.Count.EqualTo(2)); + Assert.That(result.Migrations, Has.Some.Matches(m => m.Name == "CreateTestTable")); + Assert.That(result.Migrations, Has.Some.Matches(m => m.Name == "AddColumnToTestTable")); // Cleanup Directory.Delete(tempDir, true); } + + [OneTimeTearDown] + public void OneTimeTearDown() + { + _mockLoggerFactory?.Dispose(); + } } \ No newline at end of file diff --git a/tests/MCPsharp.Tests/Services/ProjectContextManagerTests.cs b/tests/MCPsharp.Tests/Services/ProjectContextManagerTests.cs index 11a8330..14d6a4e 100644 --- a/tests/MCPsharp.Tests/Services/ProjectContextManagerTests.cs +++ b/tests/MCPsharp.Tests/Services/ProjectContextManagerTests.cs @@ -1,15 +1,15 @@ -using FluentAssertions; using MCPsharp.Services; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; -public class ProjectContextManagerTests : IDisposable +public class ProjectContextManagerTests { - private readonly string _testRoot; - private readonly ProjectContextManager _manager; + private string _testRoot = null!; + private ProjectContextManager _manager = null!; - public ProjectContextManagerTests() + [SetUp] + public void SetUp() { // Create a temporary test directory _testRoot = Path.Combine(Path.GetTempPath(), $"mcpsharp-test-{Guid.NewGuid()}"); @@ -17,7 +17,8 @@ public ProjectContextManagerTests() _manager = new ProjectContextManager(); } - public void Dispose() + [TearDown] + public void TearDown() { // Clean up test directory if (Directory.Exists(_testRoot)) @@ -26,7 +27,7 @@ public void Dispose() } } - [Fact] + [Test] public void OpenProject_ShouldSetContext_WhenValidDirectoryProvided() { // Arrange @@ -39,38 +40,36 @@ public void OpenProject_ShouldSetContext_WhenValidDirectoryProvided() var context = _manager.GetProjectContext(); // Assert - context.Should().NotBeNull(); - context!.RootPath.Should().Be(Path.GetFullPath(_testRoot)); - context.OpenedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(5)); - context.FileCount.Should().Be(3); - context.KnownFiles.Should().HaveCount(3); + Assert.That(context, Is.Not.Null); + Assert.That(context!.RootPath, Is.EqualTo(Path.GetFullPath(_testRoot))); + Assert.That(context.OpenedAt, Is.EqualTo(DateTime.UtcNow).Within(TimeSpan.FromSeconds(5))); + Assert.That(context.FileCount, Is.EqualTo(3)); + Assert.That(context.KnownFiles, Has.Count.EqualTo(3)); } - [Fact] + [Test] public void OpenProject_ShouldThrowDirectoryNotFoundException_WhenDirectoryDoesNotExist() { // Arrange var nonExistentPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); // Act & Assert - Action act = () => _manager.OpenProject(nonExistentPath); - act.Should().Throw() - .WithMessage($"Directory does not exist: {Path.GetFullPath(nonExistentPath)}"); + var ex = Assert.Throws(() => _manager.OpenProject(nonExistentPath)); + Assert.That(ex!.Message, Is.EqualTo($"Directory does not exist: {Path.GetFullPath(nonExistentPath)}")); } - [Fact] + [Test] public void OpenProject_ShouldThrowArgumentException_WhenPathIsFile() { // Arrange var filePath = CreateTestFile("testfile.txt", "test"); // Act & Assert - Action act = () => _manager.OpenProject(filePath); - act.Should().Throw() - .WithMessage($"Path is a file, not a directory: {Path.GetFullPath(filePath)}"); + var ex = Assert.Throws(() => _manager.OpenProject(filePath)); + Assert.That(ex!.Message, Is.EqualTo($"Path is a file, not a directory: {Path.GetFullPath(filePath)}")); } - [Fact] + [Test] public void OpenProject_ShouldNormalizePath_WithGetFullPath() { // Arrange @@ -82,35 +81,35 @@ public void OpenProject_ShouldNormalizePath_WithGetFullPath() var context = _manager.GetProjectContext(); // Assert - context!.RootPath.Should().Be(Path.GetFullPath(relativePath)); + Assert.That(context!.RootPath, Is.EqualTo(Path.GetFullPath(relativePath))); } - [Fact] + [Test] public void CloseProject_ShouldClearContext() { // Arrange _manager.OpenProject(_testRoot); - _manager.GetProjectContext().Should().NotBeNull(); + Assert.That(_manager.GetProjectContext(), Is.Not.Null); // Act _manager.CloseProject(); var context = _manager.GetProjectContext(); // Assert - context.Should().BeNull(); + Assert.That(context, Is.Null); } - [Fact] + [Test] public void GetProjectInfo_ShouldReturnNull_WhenNoProjectOpen() { // Act var info = _manager.GetProjectInfo(); // Assert - info.Should().BeNull(); + Assert.That(info, Is.Null); } - [Fact] + [Test] public void GetProjectInfo_ShouldReturnProjectMetadata_WhenProjectOpen() { // Arrange @@ -122,24 +121,24 @@ public void GetProjectInfo_ShouldReturnProjectMetadata_WhenProjectOpen() var info = _manager.GetProjectInfo(); // Assert - info.Should().NotBeNull(); - info!["rootPath"].Should().Be(Path.GetFullPath(_testRoot)); - info["fileCount"].Should().Be(2); - info["openedAt"].Should().BeOfType(); - info["openedAt"].ToString().Should().NotBeEmpty(); + Assert.That(info, Is.Not.Null); + Assert.That(info!["rootPath"], Is.EqualTo(Path.GetFullPath(_testRoot))); + Assert.That(info["fileCount"], Is.EqualTo(2)); + Assert.That(info["openedAt"], Is.TypeOf()); + Assert.That(info["openedAt"].ToString(), Is.Not.Empty); } - [Fact] + [Test] public void IsValidPath_ShouldReturnFalse_WhenNoProjectOpen() { // Act var isValid = _manager.IsValidPath(Path.Combine(_testRoot, "file.txt")); // Assert - isValid.Should().BeFalse(); + Assert.That(isValid, Is.False); } - [Fact] + [Test] public void IsValidPath_ShouldReturnTrue_WhenPathInsideProjectRoot() { // Arrange @@ -149,10 +148,10 @@ public void IsValidPath_ShouldReturnTrue_WhenPathInsideProjectRoot() var isValid = _manager.IsValidPath(Path.Combine(_testRoot, "subdir", "file.txt")); // Assert - isValid.Should().BeTrue(); + Assert.That(isValid, Is.True); } - [Fact] + [Test] public void IsValidPath_ShouldReturnFalse_WhenPathOutsideProjectRoot() { // Arrange @@ -163,10 +162,10 @@ public void IsValidPath_ShouldReturnFalse_WhenPathOutsideProjectRoot() var isValid = _manager.IsValidPath(outsidePath); // Assert - isValid.Should().BeFalse(); + Assert.That(isValid, Is.False); } - [Fact] + [Test] public void IsValidPath_ShouldUseCaseInsensitiveComparison() { // Arrange @@ -177,10 +176,10 @@ public void IsValidPath_ShouldUseCaseInsensitiveComparison() var isValid = _manager.IsValidPath(upperCasePath); // Assert (should work on case-insensitive file systems like Windows/macOS) - isValid.Should().BeTrue(); + Assert.That(isValid, Is.True); } - [Fact] + [Test] public void OpenProject_ShouldReplaceCurrentProject_WhenOpeningDifferentProject() { // Arrange @@ -195,17 +194,17 @@ public void OpenProject_ShouldReplaceCurrentProject_WhenOpeningDifferentProject( _manager.OpenProject(firstProject); var firstContext = _manager.GetProjectContext(); - firstContext!.FileCount.Should().Be(1); + Assert.That(firstContext!.FileCount, Is.EqualTo(1)); // Act _manager.OpenProject(secondProject); var secondContext = _manager.GetProjectContext(); // Assert - secondContext.Should().NotBeNull(); - secondContext!.RootPath.Should().Be(Path.GetFullPath(secondProject)); - secondContext.FileCount.Should().Be(1); - secondContext.RootPath.Should().NotBe(firstContext.RootPath); + Assert.That(secondContext, Is.Not.Null); + Assert.That(secondContext!.RootPath, Is.EqualTo(Path.GetFullPath(secondProject))); + Assert.That(secondContext.FileCount, Is.EqualTo(1)); + Assert.That(secondContext.RootPath, Is.Not.EqualTo(firstContext.RootPath)); } finally { @@ -217,7 +216,7 @@ public void OpenProject_ShouldReplaceCurrentProject_WhenOpeningDifferentProject( } } - [Fact] + [Test] public void OpenProject_ShouldCountFilesAccurately_WithNestedDirectories() { // Arrange @@ -233,18 +232,18 @@ public void OpenProject_ShouldCountFilesAccurately_WithNestedDirectories() var context = _manager.GetProjectContext(); // Assert - context!.FileCount.Should().Be(6); - context.KnownFiles.Should().HaveCount(6); + Assert.That(context!.FileCount, Is.EqualTo(6)); + Assert.That(context.KnownFiles, Has.Count.EqualTo(6)); } - [Fact] + [Test] public void GetProjectContext_ShouldReturnNull_InitiallyBeforeOpeningProject() { // Act var context = _manager.GetProjectContext(); // Assert - context.Should().BeNull(); + Assert.That(context, Is.Null); } private string CreateTestFile(string relativePath, string content) diff --git a/tests/MCPsharp.Tests/Services/ResponseProcessorTests.cs b/tests/MCPsharp.Tests/Services/ResponseProcessorTests.cs index 6060357..50fc6b5 100644 --- a/tests/MCPsharp.Tests/Services/ResponseProcessorTests.cs +++ b/tests/MCPsharp.Tests/Services/ResponseProcessorTests.cs @@ -1,16 +1,17 @@ using Microsoft.Extensions.Logging; using MCPsharp.Models; using MCPsharp.Services; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; public class ResponseProcessorTests { - private readonly ResponseConfiguration _defaultConfig; - private readonly ResponseProcessor _processor; + private ResponseConfiguration _defaultConfig = null!; + private ResponseProcessor _processor = null!; - public ResponseProcessorTests() + [SetUp] + public void SetUp() { _defaultConfig = new ResponseConfiguration { @@ -21,7 +22,7 @@ public ResponseProcessorTests() _processor = new ResponseProcessor(_defaultConfig); } - [Fact] + [Test] public void ProcessResponse_SmallResponse_ShouldNotTruncate() { // Arrange @@ -32,12 +33,12 @@ public void ProcessResponse_SmallResponse_ShouldNotTruncate() var result = _processor.ProcessResponse(smallResponse, toolName); // Assert - Assert.False(result.WasTruncated); - Assert.Equal(result.EstimatedTokenCount, result.OriginalTokenCount); - Assert.Null(result.Warning); + Assert.That(result.WasTruncated, Is.False); + Assert.That(result.EstimatedTokenCount, Is.EqualTo(result.OriginalTokenCount)); + Assert.That(result.Warning, Is.Null); } - [Fact] + [Test] public void ProcessResponse_LargeResponse_ShouldTruncate() { // Arrange @@ -52,13 +53,13 @@ public void ProcessResponse_LargeResponse_ShouldTruncate() var result = _processor.ProcessResponse(largeResponse, toolName); // Assert - Assert.True(result.WasTruncated); - Assert.True(result.EstimatedTokenCount <= _defaultConfig.MaxTokens); - Assert.True(result.OriginalTokenCount > _defaultConfig.MaxTokens); - Assert.NotNull(result.Warning); + Assert.That(result.WasTruncated, Is.True); + Assert.That(result.EstimatedTokenCount, Is.LessThanOrEqualTo(_defaultConfig.MaxTokens)); + Assert.That(result.OriginalTokenCount, Is.GreaterThan(_defaultConfig.MaxTokens)); + Assert.That(result.Warning, Is.Not.Null); } - [Fact] + [Test] public void ProcessResponse_ExemptTool_ShouldNotTruncate() { // Arrange @@ -76,12 +77,12 @@ public void ProcessResponse_ExemptTool_ShouldNotTruncate() var result = processor.ProcessResponse(largeResponse, toolName); // Assert - Assert.False(result.WasTruncated); - Assert.True(result.EstimatedTokenCount > config.MaxTokens); - Assert.True(result.Metadata.ContainsKey("exempt")); + Assert.That(result.WasTruncated, Is.False); + Assert.That(result.EstimatedTokenCount, Is.GreaterThan(config.MaxTokens)); + Assert.That(result.Metadata.ContainsKey("exempt"), Is.True); } - [Fact] + [Test] public void ProcessResponse_TruncationDisabled_ShouldReturnError() { // Arrange @@ -98,17 +99,16 @@ public void ProcessResponse_TruncationDisabled_ShouldReturnError() var result = processor.ProcessResponse(largeResponse, toolName); // Assert - Assert.False(result.WasTruncated); - Assert.True(result.EstimatedTokenCount > config.MaxTokens); - Assert.NotNull(result.Warning); - Assert.Contains("exceeds token limit", result.Warning); + Assert.That(result.WasTruncated, Is.False); + Assert.That(result.EstimatedTokenCount, Is.GreaterThan(config.MaxTokens)); + Assert.That(result.Warning, Is.Not.Null); + Assert.That(result.Warning, Does.Contain("exceeds token limit")); } - [Theory] - [InlineData(SummaryStyle.Ellipsis)] - [InlineData(SummaryStyle.Paragraphs)] - [InlineData(SummaryStyle.JsonStructure)] - [InlineData(SummaryStyle.LineBased)] + [TestCase(SummaryStyle.Ellipsis)] + [TestCase(SummaryStyle.Paragraphs)] + [TestCase(SummaryStyle.JsonStructure)] + [TestCase(SummaryStyle.LineBased)] public void ProcessResponse_DifferentSummaryStyles_ShouldProduceValidResults(SummaryStyle style) { // Arrange @@ -132,12 +132,12 @@ public void ProcessResponse_DifferentSummaryStyles_ShouldProduceValidResults(Sum var result = processor.ProcessResponse(largeResponse, toolName); // Assert - Assert.True(result.EstimatedTokenCount <= config.MaxTokens); - Assert.NotNull(result.Content); - Assert.Contains(style.ToString(), result.Metadata.GetValueOrDefault("truncationStyle")?.ToString() ?? ""); + Assert.That(result.EstimatedTokenCount, Is.LessThanOrEqualTo(config.MaxTokens)); + Assert.That(result.Content, Is.Not.Null); + Assert.That(result.Metadata.GetValueOrDefault("truncationStyle")?.ToString() ?? "", Does.Contain(style.ToString())); } - [Fact] + [Test] public void ProcessResponse_NearWarningThreshold_ShouldIncludeWarning() { // Arrange @@ -154,12 +154,12 @@ public void ProcessResponse_NearWarningThreshold_ShouldIncludeWarning() var result = processor.ProcessResponse(mediumResponse, toolName); // Assert - Assert.False(result.WasTruncated); - Assert.NotNull(result.Warning); - Assert.Contains("using", result.Warning); + Assert.That(result.WasTruncated, Is.False); + Assert.That(result.Warning, Is.Not.Null); + Assert.That(result.Warning, Does.Contain("using")); } - [Fact] + [Test] public void LoadFromEnvironment_ShouldApplyEnvironmentVariables() { // Arrange @@ -172,12 +172,12 @@ public void LoadFromEnvironment_ShouldApplyEnvironmentVariables() var config = ResponseConfiguration.LoadFromEnvironment(); // Assert - Assert.Equal(500, config.MaxTokens); - Assert.False(config.EnableTruncation); - Assert.Equal(SummaryStyle.JsonStructure, config.SummaryStyle); - Assert.Contains("tool1", config.ExemptTools); - Assert.Contains("tool2", config.ExemptTools); - Assert.Contains("tool3", config.ExemptTools); + Assert.That(config.MaxTokens, Is.EqualTo(500)); + Assert.That(config.EnableTruncation, Is.False); + Assert.That(config.SummaryStyle, Is.EqualTo(SummaryStyle.JsonStructure)); + Assert.That(config.ExemptTools, Does.Contain("tool1")); + Assert.That(config.ExemptTools, Does.Contain("tool2")); + Assert.That(config.ExemptTools, Does.Contain("tool3")); // Cleanup Environment.SetEnvironmentVariable("MCP_MAX_TOKENS", null); @@ -186,7 +186,7 @@ public void LoadFromEnvironment_ShouldApplyEnvironmentVariables() Environment.SetEnvironmentVariable("MCP_EXEMPT_TOOLS", null); } - [Fact] + [Test] public void ProcessResponse_WildcardExemption_ShouldMatchPattern() { // Arrange @@ -200,14 +200,14 @@ public void ProcessResponse_WildcardExemption_ShouldMatchPattern() // Act & Assert - stream tools should be exempt var streamResult = processor.ProcessResponse(largeResponse, "stream_process_file"); - Assert.False(streamResult.WasTruncated); + Assert.That(streamResult.WasTruncated, Is.False); // Act & Assert - bulk tools should be exempt var bulkResult = processor.ProcessResponse(largeResponse, "bulk_replace"); - Assert.False(bulkResult.WasTruncated); + Assert.That(bulkResult.WasTruncated, Is.False); // Act & Assert - other tools should not be exempt var otherResult = processor.ProcessResponse(largeResponse, "other_tool"); - Assert.True(otherResult.WasTruncated); + Assert.That(otherResult.WasTruncated, Is.True); } -} \ No newline at end of file +} diff --git a/tests/MCPsharp.Tests/Services/Roslyn/AdvancedReferenceFinderServiceTests.cs b/tests/MCPsharp.Tests/Services/Roslyn/AdvancedReferenceFinderServiceTests.cs index 914e39e..bea09c7 100644 --- a/tests/MCPsharp.Tests/Services/Roslyn/AdvancedReferenceFinderServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/Roslyn/AdvancedReferenceFinderServiceTests.cs @@ -98,11 +98,11 @@ public async Task FindCallersAsync_WithValidParameters_ShouldReturnCallerResult( var result = await _service.FindCallersAsync(methodName, containingType, true); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); if (result == null) throw new InvalidOperationException("Result should not be null"); Assert.That(result.TargetSymbol, Is.EqualTo(methodName)); - Assert.NotNull(result.TargetSignature); + Assert.That(result.TargetSignature, Is.Not.Null); if (result.TargetSignature == null) throw new InvalidOperationException("TargetSignature should not be null"); Assert.That(result.TargetSignature.ContainingType, Is.EqualTo(containingType)); @@ -197,10 +197,10 @@ public async Task FindCallersAtLocationAsync_WithValidLocation_ShouldReturnCalle var result = await _service.FindCallersAtLocationAsync(filePath, line, column, false); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); if (result == null) throw new InvalidOperationException("Result should not be null"); - Assert.NotNull(result.TargetSignature); + Assert.That(result.TargetSignature, Is.Not.Null); if (result.TargetSignature == null) throw new InvalidOperationException("TargetSignature should not be null"); Assert.That(result.TargetSignature.Name, Is.EqualTo("ProcessData")); @@ -275,10 +275,10 @@ public async Task FindCallersAtLocationAsync_WithIndirectFalse_ShouldFilterToDir var result = await _service.FindCallersAtLocationAsync(filePath, line, column, false); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); if (result == null) throw new InvalidOperationException("Result should not be null"); - Assert.NotNull(result.Callers); + Assert.That(result.Callers, Is.Not.Null); if (result.Callers == null) throw new InvalidOperationException("Callers should not be null"); Assert.That(result.Callers.Count, Is.EqualTo(1)); @@ -330,10 +330,10 @@ public async Task FindCallChainsAsync_WithValidParameters_ShouldReturnCallChains var result = await _service.FindCallChainsAsync(methodName, containingType, direction, maxDepth); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); if (result == null) throw new InvalidOperationException("Result should not be null"); - Assert.NotNull(result.TargetMethod); + Assert.That(result.TargetMethod, Is.Not.Null); if (result.TargetMethod == null) throw new InvalidOperationException("TargetMethod should not be null"); Assert.That(result.TargetMethod.Name, Is.EqualTo(methodName)); @@ -532,8 +532,8 @@ public async Task AnalyzeCallPatternsAsync_WithValidMethod_ShouldReturnAnalysis( var result = await _service.AnalyzeCallPatternsAsync(methodName, containingType); // Assert - Assert.NotNull(result); - Assert.NotNull(result.TargetMethod); + Assert.That(result, Is.Not.Null); + Assert.That(result.TargetMethod, Is.Not.Null); Assert.That(result.TargetMethod.Name, Is.EqualTo(methodName)); Assert.That(result.TargetMethod.ContainingType, Is.EqualTo(containingType)); @@ -729,9 +729,9 @@ public async Task AnalyzeCallGraphAsync_WithTypeFilter_ShouldReturnCallGraphAnal var result = await _service.AnalyzeCallGraphAsync(typeName); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); Assert.That(result.Scope, Is.EqualTo(typeName)); - Assert.NotNull(result.Methods); + Assert.That(result.Methods, Is.Not.Null); Assert.That(result.Methods.Count, Is.EqualTo(15)); await _mockCallChain.Received(1).AnalyzeCallGraphAsync(typeName, null, Arg.Any()); diff --git a/tests/MCPsharp.Tests/Services/Roslyn/ExtractMethodServiceTests.cs b/tests/MCPsharp.Tests/Services/Roslyn/ExtractMethodServiceTests.cs index 9427594..bb0c92d 100644 --- a/tests/MCPsharp.Tests/Services/Roslyn/ExtractMethodServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/Roslyn/ExtractMethodServiceTests.cs @@ -1,16 +1,17 @@ using MCPsharp.Services.Roslyn; using MCPsharp.Models.Refactoring; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services.Roslyn; -public class ExtractMethodServiceTests : IAsyncLifetime +public class ExtractMethodServiceTests { private RoslynWorkspace _workspace = null!; private ExtractMethodService _service = null!; private string _testProjectPath = null!; - public async Task InitializeAsync() + [SetUp] + public async Task SetUp() { _testProjectPath = Path.Combine(Path.GetTempPath(), "ExtractMethodTests_" + Guid.NewGuid()); Directory.CreateDirectory(_testProjectPath); @@ -21,7 +22,8 @@ public async Task InitializeAsync() _service = new ExtractMethodService(_workspace); } - public async Task DisposeAsync() + [TearDown] + public async Task TearDown() { _workspace?.Dispose(); @@ -43,7 +45,7 @@ private async Task CreateTestFileAsync(string fileName, string content) #region Basic Extraction Tests - [Fact] + [Test] public async Task ExtractMethod_SimpleStatements_Success() { var code = @" @@ -73,13 +75,13 @@ public void ProcessData() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.NotNull(result.Extraction); - Assert.Equal("CalculateSum", result.Extraction.Method.Name); - Assert.Contains("private", result.Extraction.Method.Signature); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction, Is.Not.Null); + Assert.That(result.Extraction.Method.Name, Is.EqualTo("CalculateSum")); + Assert.That(result.Extraction.Method.Signature, Does.Contain("private")); } - [Fact] + [Test] public async Task ExtractMethod_WithParameters_InfersCorrectly() { var code = @" @@ -108,14 +110,14 @@ public void Calculate() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.NotNull(result.Extraction); - Assert.Equal(2, result.Extraction.Parameters.Count); - Assert.Contains(result.Extraction.Parameters, p => p.Name == "a"); - Assert.Contains(result.Extraction.Parameters, p => p.Name == "result" && p.Modifier == "out"); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction, Is.Not.Null); + Assert.That(result.Extraction.Parameters.Count, Is.EqualTo(2)); + Assert.That(result.Extraction.Parameters, Does.Contain(result.Extraction.Parameters.FirstOrDefault(p => p.Name == "a"))); + Assert.That(result.Extraction.Parameters, Does.Contain(result.Extraction.Parameters.FirstOrDefault(p => p.Name == "result" && p.Modifier == "out"))); } - [Fact] + [Test] public async Task ExtractMethod_WithReturnValue_InfersCorrectly() { var code = @" @@ -144,12 +146,12 @@ public void Calculate() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.NotNull(result.Extraction); - Assert.NotEqual("void", result.Extraction.ReturnType); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction, Is.Not.Null); + Assert.That(result.Extraction.ReturnType, Is.Not.EqualTo("void")); } - [Fact] + [Test] public async Task ExtractMethod_VoidMethod_NoReturnValue() { var code = @" @@ -176,8 +178,8 @@ public void Process() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.NotNull(result.Extraction); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction, Is.Not.Null); // If the variable isn't used after, it might still be void } @@ -185,7 +187,7 @@ public void Process() #region Async/Await Tests - [Fact] + [Test] public async Task ExtractMethod_WithAwait_CreatesAsyncMethod() { var code = @" @@ -218,16 +220,16 @@ public async Task ProcessAsync() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.NotNull(result.Extraction); - Assert.True(result.Extraction.Characteristics.IsAsync); - Assert.True(result.Extraction.Characteristics.ContainsAwait); - Assert.Contains("async", result.Extraction.Method.Signature); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction, Is.Not.Null); + Assert.That(result.Extraction.Characteristics.IsAsync, Is.True); + Assert.That(result.Extraction.Characteristics.ContainsAwait, Is.True); + Assert.That(result.Extraction.Method.Signature, Does.Contain("async")); // For now, just check that return type is detected (may be empty due to extraction limitations) // TODO: Fix return type detection for async methods to properly include "Task" if (!string.IsNullOrEmpty(result.Extraction.ReturnType)) { - Assert.Contains("Task", result.Extraction.ReturnType); + Assert.That(result.Extraction.ReturnType, Does.Contain("Task")); } } @@ -235,7 +237,7 @@ public async Task ProcessAsync() #region Error Cases - [Fact] + [Test] public async Task ExtractMethod_InvalidLineRange_ReturnsError() { var code = @" @@ -259,11 +261,11 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.False(result.Success); - Assert.NotNull(result.Error); + Assert.That(result.Success, Is.False); + Assert.That(result.Error, Is.Not.Null); } - [Fact] + [Test] public async Task ExtractMethod_NoStatements_ReturnsError() { var code = @" @@ -287,10 +289,10 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.False(result.Success); + Assert.That(result.Success, Is.False); } - [Fact] + [Test] public async Task ExtractMethod_WithGoto_ReturnsError() { var code = @" @@ -318,11 +320,11 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.False(result.Success); - Assert.Contains("goto", result.Error?.Message ?? "", StringComparison.OrdinalIgnoreCase); + Assert.That(result.Success, Is.False); + Assert.That(result.Error?.Message ?? "", Does.Contain("goto").IgnoreCase); } - [Fact] + [Test] public async Task ExtractMethod_NotInMethod_ReturnsError() { var code = @" @@ -343,14 +345,14 @@ class Test var result = await _service.ExtractMethodAsync(request); - Assert.False(result.Success); + Assert.That(result.Success, Is.False); } #endregion #region Preview Tests - [Fact] + [Test] public async Task ExtractMethod_PreviewMode_ReturnsPreview() { var code = @" @@ -376,17 +378,17 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.NotNull(result.Preview); - Assert.NotEmpty(result.Preview.OriginalCode); - Assert.NotEmpty(result.Preview.ModifiedCode); + Assert.That(result.Success, Is.True); + Assert.That(result.Preview, Is.Not.Null); + Assert.That(result.Preview.OriginalCode, Is.Not.Empty); + Assert.That(result.Preview.ModifiedCode, Is.Not.Empty); } #endregion #region Method Characteristics Tests - [Fact] + [Test] public async Task ExtractMethod_MultipleStatements_DetectsCorrectly() { var code = @" @@ -416,11 +418,11 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.NotNull(result.Extraction); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction, Is.Not.Null); } - [Fact] + [Test] public async Task ExtractMethod_ComplexExpression_HandlesCorrectly() { var code = @" @@ -450,14 +452,14 @@ public void Calculate() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); + Assert.That(result.Success, Is.True); } #endregion #region Accessibility Tests - [Fact] + [Test] public async Task ExtractMethod_PublicAccessibility_GeneratesCorrectly() { var code = @" @@ -483,11 +485,11 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.Contains("public", result.Extraction!.Method.Signature); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction!.Method.Signature, Does.Contain("public")); } - [Fact] + [Test] public async Task ExtractMethod_DefaultPrivate_GeneratesCorrectly() { var code = @" @@ -511,15 +513,15 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.Contains("private", result.Extraction!.Method.Signature); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction!.Method.Signature, Does.Contain("private")); } #endregion #region Custom Method Name Tests - [Fact] + [Test] public async Task ExtractMethod_CustomName_UsesProvidedName() { var code = @" @@ -544,11 +546,11 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.Equal("MyCustomMethod", result.Extraction!.Method.Name); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction!.Method.Name, Is.EqualTo("MyCustomMethod")); } - [Fact] + [Test] public async Task ExtractMethod_NoName_GeneratesDefault() { var code = @" @@ -572,15 +574,15 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.NotEmpty(result.Extraction!.Method.Name); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction!.Method.Name, Is.Not.Empty); } #endregion #region Data Flow Tests - [Fact] + [Test] public async Task ExtractMethod_ReadOnlyVariable_PassesAsParameter() { var code = @" @@ -607,12 +609,12 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.Contains(result.Extraction!.Parameters, p => p.Name == "value"); - Assert.Null(result.Extraction.Parameters.First(p => p.Name == "value").Modifier); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction!.Parameters, Does.Contain(result.Extraction.Parameters.FirstOrDefault(p => p.Name == "value"))); + Assert.That(result.Extraction.Parameters.First(p => p.Name == "value").Modifier, Is.Null); } - [Fact] + [Test] public async Task ExtractMethod_ModifiedVariable_UsesRef() { var code = @" @@ -639,7 +641,7 @@ public void Method() var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); + Assert.That(result.Success, Is.True); // Should have ref parameter for counter } @@ -647,7 +649,7 @@ public void Method() #region Integration Tests - [Fact] + [Test] public async Task ExtractMethod_RealWorldScenario_Success() { var code = @" @@ -713,9 +715,9 @@ public class OrderItem var result = await _service.ExtractMethodAsync(request); - Assert.True(result.Success); - Assert.Equal("CalculateOrderTotals", result.Extraction!.Method.Name); - Assert.NotNull(result.Preview); + Assert.That(result.Success, Is.True); + Assert.That(result.Extraction!.Method.Name, Is.EqualTo("CalculateOrderTotals")); + Assert.That(result.Preview, Is.Not.Null); } #endregion diff --git a/tests/MCPsharp.Tests/Services/Roslyn/RenameSymbolServiceTests.cs b/tests/MCPsharp.Tests/Services/Roslyn/RenameSymbolServiceTests.cs index ac75a3e..9ce6eb1 100644 --- a/tests/MCPsharp.Tests/Services/Roslyn/RenameSymbolServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/Roslyn/RenameSymbolServiceTests.cs @@ -1,4 +1,4 @@ -using Xunit; +using NUnit.Framework; using Microsoft.Extensions.Logging; using Microsoft.CodeAnalysis; using NSubstitute; @@ -12,11 +12,12 @@ namespace MCPsharp.Tests.Services.Roslyn; /// public class RenameSymbolServiceTests : TestBase { - private readonly RenameSymbolService _service; - private readonly RoslynWorkspace _workspace; - private readonly ILogger _logger; + private RenameSymbolService _service = null!; + private RoslynWorkspace _workspace = null!; + private ILogger _logger = null!; - public RenameSymbolServiceTests() + [SetUp] + public void SetUp() { _workspace = new RoslynWorkspace(); var referenceFinder = new AdvancedReferenceFinderService( @@ -45,7 +46,7 @@ public RenameSymbolServiceTests() #region Basic Rename Tests - [Fact] + [Test] public async Task RenameLocalVariable_Success() { // Arrange @@ -66,8 +67,8 @@ public void TestMethod() // DEBUG: Check workspace state var documents = _workspace.GetAllDocuments().ToList(); var compilation = _workspace.GetCompilation(); - Assert.NotEmpty(documents); // Should have 1 document - Assert.NotNull(compilation); // Should have a compilation + Assert.That(documents, Is.Not.Empty); // Should have 1 document + Assert.That(compilation, Is.Not.Null); // Should have a compilation var request = new RenameRequest { @@ -86,13 +87,13 @@ public void TestMethod() Console.WriteLine($"Errors: {string.Join(", ", result.Errors)}"); // Assert with diagnostic information - Assert.True(result.Success, $"Rename failed. Errors: [{string.Join(", ", result.Errors)}], Conflicts: {result.Conflicts.Count}"); + Assert.That(result.Success, Is.True, $"Rename failed. Errors: [{string.Join(", ", result.Errors)}], Conflicts: {result.Conflicts.Count}"); // TODO: Figure out why only 1 reference is being renamed instead of 3 - //Assert.Equal(3, result.RenamedCount); // 3 references to the variable - Assert.Single(result.FilesModified); + //Assert.That(result.RenamedCount, Is.EqualTo(3)); // 3 references to the variable + Assert.That(result.FilesModified, Has.Count.EqualTo(1)); } - [Fact] + [Test] public async Task RenameParameter_UpdatesAllReferences() { // Arrange @@ -126,16 +127,16 @@ public void Caller() var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success, $"Rename failed. Errors: [{string.Join(", ", result.Errors)}], Conflicts: {result.Conflicts.Count}"); + Assert.That(result.Success, Is.True, $"Rename failed. Errors: [{string.Join(", ", result.Errors)}], Conflicts: {result.Conflicts.Count}"); // TODO: Check renamed count - //Assert.True(result.RenamedCount >= 4); // Declaration + 3 uses + named argument + //Assert.That(result.RenamedCount >= 4, Is.True); // Declaration + 3 uses + named argument } #endregion #region Class Rename Tests - [Fact] + [Test] public async Task RenameClass_UpdatesAllReferences() { // Arrange @@ -179,11 +180,11 @@ public void UseClass() Console.WriteLine($"Errors: {string.Join(", ", result.Errors)}"); // Assert - Assert.True(result.Success, $"Rename failed. Errors: [{string.Join(", ", result.Errors)}], Conflicts: [{string.Join("; ", result.Conflicts.Select(c => c.Description))}]"); - Assert.True(result.RenamedCount >= 6, $"Expected >= 6 renames, got {result.RenamedCount}"); // Class declaration, constructor, return types, instantiations + Assert.That(result.Success, Is.True, $"Rename failed. Errors: [{string.Join(", ", result.Errors)}], Conflicts: [{string.Join("; ", result.Conflicts.Select(c => c.Description))}]"); + Assert.That(result.RenamedCount >= 6, Is.True, $"Expected >= 6 renames, got {result.RenamedCount}"); // Class declaration, constructor, return types, instantiations } - [Fact] + [Test] public async Task RenamePartialClass_UpdatesAllParts() { // Arrange @@ -215,15 +216,15 @@ public void Method2() { } var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success); - Assert.Equal(2, result.FilesModified.Count); // Both files should be modified + Assert.That(result.Success, Is.True); + Assert.That(result.FilesModified.Count, Is.EqualTo(2)); // Both files should be modified } #endregion #region Interface and Implementation Tests - [Fact] + [Test] public async Task RenameInterface_UpdatesImplementations() { // Arrange @@ -261,11 +262,11 @@ public void UseInterface(IOldInterface instance) var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success); - Assert.True(result.RenamedCount >= 3); // Interface declaration, implementation, parameter type + Assert.That(result.Success, Is.True); + Assert.That(result.RenamedCount >= 3, Is.True); // Interface declaration, implementation, parameter type } - [Fact] + [Test] public async Task RenameInterfaceMethod_UpdatesImplementations() { // Arrange @@ -307,15 +308,15 @@ void IService.OldMethod() var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success); - Assert.True(result.RenamedCount >= 3); // Interface method + implicit impl + explicit impl + Assert.That(result.Success, Is.True); + Assert.That(result.RenamedCount >= 3, Is.True); // Interface method + implicit impl + explicit impl } #endregion #region Method Rename Tests - [Fact] + [Test] public async Task RenameVirtualMethod_UpdatesOverrides() { // Arrange @@ -358,11 +359,11 @@ public void Test() var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success, $"Rename failed. Errors: [{string.Join(", ", result.Errors)}], Conflicts: [{string.Join("; ", result.Conflicts.Select(c => c.Description))}]"); - Assert.True(result.RenamedCount >= 4); // Virtual declaration, override, base call, instance call + Assert.That(result.Success, Is.True, $"Rename failed. Errors: [{string.Join(", ", result.Errors)}], Conflicts: [{string.Join("; ", result.Conflicts.Select(c => c.Description))}]"); + Assert.That(result.RenamedCount >= 4, Is.True); // Virtual declaration, override, base call, instance call } - [Fact] + [Test] public async Task RenameOverloadedMethod_SingleOverload() { // Arrange @@ -397,7 +398,7 @@ public void Test() var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success); + Assert.That(result.Success, Is.True); // Should rename only one overload and its calls } @@ -405,7 +406,7 @@ public void Test() #region Property Rename Tests - [Fact] + [Test] public async Task RenameProperty_WithBackingField() { // Arrange @@ -442,11 +443,11 @@ public void Test() var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success); - Assert.True(result.RenamedCount >= 3); // Property declaration + 2 uses + Assert.That(result.Success, Is.True); + Assert.That(result.RenamedCount >= 3, Is.True); // Property declaration + 2 uses } - [Fact] + [Test] public async Task RenameAutoProperty_Success() { // Arrange @@ -477,15 +478,15 @@ public void Test() var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success, $"Rename failed. Errors: [{string.Join(", ", result.Errors)}], Conflicts: {result.Conflicts.Count}"); - Assert.True(result.RenamedCount >= 3); // Property declaration + 2 uses + Assert.That(result.Success, Is.True, $"Rename failed. Errors: [{string.Join(", ", result.Errors)}], Conflicts: {result.Conflicts.Count}"); + Assert.That(result.RenamedCount >= 3, Is.True); // Property declaration + 2 uses } #endregion #region Conflict Detection Tests - [Fact] + [Test] public async Task RenameWithNameCollision_ReturnsError() { // Arrange @@ -511,12 +512,12 @@ public class TestClass var result = await _service.RenameSymbolAsync(request); // Assert - Assert.False(result.Success); - Assert.NotEmpty(result.Conflicts); - Assert.Contains(result.Conflicts, c => c.Type == ConflictType.NameCollision); + Assert.That(result.Success, Is.False); + Assert.That(result.Conflicts, Is.Not.Empty); + Assert.That(result.Conflicts, Does.Contain(result.Conflicts.FirstOrDefault(c => c.Type == ConflictType.NameCollision))); } - [Fact] + [Test] public async Task RenameHidingInheritedMember_ReturnsWarning() { // Arrange @@ -548,14 +549,14 @@ public void OldMethod() { } // Assert // Should have warning about hiding inherited member - Assert.Contains(result.Conflicts, c => c.Type == ConflictType.HidesInheritedMember); + Assert.That(result.Conflicts, Does.Contain(result.Conflicts.FirstOrDefault(c => c.Type == ConflictType.HidesInheritedMember))); } #endregion #region Validation Tests - [Fact] + [Test] public async Task RenameToInvalidIdentifier_ReturnsError() { // Arrange @@ -573,11 +574,11 @@ public async Task RenameToInvalidIdentifier_ReturnsError() var result = await _service.RenameSymbolAsync(request); // Assert - Assert.False(result.Success); - Assert.Contains("not a valid C# identifier", result.Errors[0]); + Assert.That(result.Success, Is.False); + Assert.That(result.Errors[0], Does.Contain("not a valid C# identifier")); } - [Fact] + [Test] public async Task RenameToKeyword_RequiresFlag() { // Arrange @@ -596,11 +597,11 @@ public async Task RenameToKeyword_RequiresFlag() var result = await _service.RenameSymbolAsync(request); // Assert - Assert.False(result.Success); - Assert.Contains("is a C# keyword", result.Errors[0]); + Assert.That(result.Success, Is.False); + Assert.That(result.Errors[0], Does.Contain("is a C# keyword")); } - [Fact] + [Test] public async Task RenameNonExistentSymbol_ReturnsError() { // Arrange @@ -618,15 +619,15 @@ public async Task RenameNonExistentSymbol_ReturnsError() var result = await _service.RenameSymbolAsync(request); // Assert - Assert.False(result.Success); - Assert.Contains("not found", result.Errors[0]); + Assert.That(result.Success, Is.False); + Assert.That(result.Errors[0], Does.Contain("not found")); } #endregion #region Preview Mode Tests - [Fact] + [Test] public async Task RenameInPreviewMode_DoesNotApplyChanges() { // Arrange @@ -655,23 +656,23 @@ public void Test() var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success); - Assert.NotNull(result.Preview); - Assert.NotEmpty(result.Preview); + Assert.That(result.Success, Is.True); + Assert.That(result.Preview, Is.Not.Null); + Assert.That(result.Preview, Is.Not.Empty); // Verify original code is unchanged var document = _workspace.GetDocument("test.cs"); - Assert.NotNull(document); + Assert.That(document, Is.Not.Null); var text = await document.GetTextAsync(); - Assert.Contains("OldName", text.ToString()); - Assert.DoesNotContain("NewName", text.ToString()); + Assert.That(text.ToString(), Does.Contain("OldName")); + Assert.That(text.ToString(), Does.Not.Contain("NewName")); } #endregion #region Edge Case Tests - [Fact] + [Test] public async Task RenameConstructor_HandledSpecially() { // Arrange @@ -697,11 +698,11 @@ public OldClass(int value) { } var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success); + Assert.That(result.Success, Is.True); // Constructors should be renamed with the class } - [Fact] + [Test] public async Task RenameNamespace_Success() { // Arrange @@ -736,11 +737,11 @@ public class User var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success); - Assert.True(result.RenamedCount >= 2); // Namespace declaration + using statement + Assert.That(result.Success, Is.True); + Assert.That(result.RenamedCount >= 2, Is.True); // Namespace declaration + using statement } - [Fact] + [Test] public async Task RenameGenericTypeParameter_Success() { // Arrange @@ -768,9 +769,15 @@ public class Container var result = await _service.RenameSymbolAsync(request); // Assert - Assert.True(result.Success); - Assert.True(result.RenamedCount >= 4); // Declaration + 3 uses + Assert.That(result.Success, Is.True); + Assert.That(result.RenamedCount >= 4, Is.True); // Declaration + 3 uses } #endregion + + [TearDown] + public void TearDown() + { + _workspace?.Dispose(); + } } \ No newline at end of file diff --git a/tests/MCPsharp.Tests/Services/Roslyn/RoslynWorkspaceInitializationTests.cs b/tests/MCPsharp.Tests/Services/Roslyn/RoslynWorkspaceInitializationTests.cs index 7695e24..dbe8df2 100644 --- a/tests/MCPsharp.Tests/Services/Roslyn/RoslynWorkspaceInitializationTests.cs +++ b/tests/MCPsharp.Tests/Services/Roslyn/RoslynWorkspaceInitializationTests.cs @@ -1,5 +1,5 @@ using MCPsharp.Services.Roslyn; -using Xunit; +using NUnit.Framework; using System.IO; using System.Linq; using System.Threading.Tasks; @@ -11,7 +11,7 @@ namespace MCPsharp.Tests.Services.Roslyn; /// public class RoslynWorkspaceInitializationTests { - [Fact] + [Test] public async Task InitializeAsync_WithRealProject_LoadsWithoutErrors() { // Arrange @@ -19,6 +19,7 @@ public async Task InitializeAsync_WithRealProject_LoadsWithoutErrors() if (!Directory.Exists(projectPath)) { // Skip test if project directory not found + Assert.Ignore("Project directory not found"); return; } @@ -29,30 +30,31 @@ public async Task InitializeAsync_WithRealProject_LoadsWithoutErrors() var health = workspace.GetHealth(); // Assert - Assert.True(health.IsInitialized, "Workspace should be initialized"); - Assert.True(health.LoadedProjects > 0, "At least one project should be loaded"); - Assert.True(health.TotalFiles > 0, "Should have source files"); - Assert.True(health.ParseableFiles > 0, "Should have parseable files"); + Assert.That(health.IsInitialized, Is.True, "Workspace should be initialized"); + Assert.That(health.LoadedProjects > 0, Is.True, "At least one project should be loaded"); + Assert.That(health.TotalFiles > 0, Is.True, "Should have source files"); + Assert.That(health.ParseableFiles > 0, Is.True, "Should have parseable files"); // The key assertion: error count should match actual build (0 errors) // Previously this was 179 errors due to missing NuGet references - Assert.True(health.ErrorCount < 50, + Assert.That(health.ErrorCount < 50, Is.True, $"Error count should be low (< 50), but got {health.ErrorCount}. " + $"This indicates MSBuildWorkspace is loading references correctly."); // Verify semantic operations are available or close to being available - Assert.True(health.CanDoSyntaxOperations, "Should be able to do syntax operations"); + Assert.That(health.CanDoSyntaxOperations, Is.True, "Should be able to do syntax operations"); workspace.Dispose(); } - [Fact] + [Test] public async Task InitializeAsync_WithRealProject_CanFindSymbols() { // Arrange var projectPath = GetProjectPath(); if (!Directory.Exists(projectPath)) { + Assert.Ignore("Project directory not found"); return; } @@ -63,8 +65,8 @@ public async Task InitializeAsync_WithRealProject_CanFindSymbols() var compilation = workspace.GetCompilation(); // Assert - Assert.NotNull(compilation); - Assert.True(compilation.References.Count() > 5, + Assert.That(compilation, Is.Not.Null); + Assert.That(compilation.References.Count() > 5, Is.True, $"Should have many references from NuGet packages, got {compilation.References.Count()}"); // Verify we can find a known type (proves references are loaded) @@ -72,12 +74,12 @@ public async Task InitializeAsync_WithRealProject_CanFindSymbols() n => n == "RoslynWorkspace", Microsoft.CodeAnalysis.SymbolFilter.Type); - Assert.NotEmpty(symbolsWithName); + Assert.That(symbolsWithName, Is.Not.Empty); workspace.Dispose(); } - [Fact] + [Test] public async Task InitializeAsync_WithSolutionFile_LoadsSuccessfully() { // Arrange @@ -85,6 +87,7 @@ public async Task InitializeAsync_WithSolutionFile_LoadsSuccessfully() if (!File.Exists(slnPath)) { // Skip test if solution not found + Assert.Ignore("Solution file not found"); return; } @@ -95,19 +98,19 @@ public async Task InitializeAsync_WithSolutionFile_LoadsSuccessfully() var health = workspace.GetHealth(); // Assert - Assert.True(health.IsInitialized, "Workspace should be initialized from .sln file"); - Assert.True(health.LoadedProjects > 0, "At least one project should be loaded from solution"); - Assert.True(health.TotalFiles > 0, "Should have source files"); + Assert.That(health.IsInitialized, Is.True, "Workspace should be initialized from .sln file"); + Assert.That(health.LoadedProjects > 0, Is.True, "At least one project should be loaded from solution"); + Assert.That(health.TotalFiles > 0, Is.True, "Should have source files"); // The key fix: error count should be low, not 15k - Assert.True(health.ErrorCount < 50, + Assert.That(health.ErrorCount < 50, Is.True, $"Error count should be low (< 50), but got {health.ErrorCount}. " + $"Regression test: Previously passing .sln file caused fallback to AdhocWorkspace with 15k errors."); workspace.Dispose(); } - [Fact] + [Test] public async Task InitializeAsync_WithCsprojFile_LoadsSuccessfully() { // Arrange @@ -115,6 +118,7 @@ public async Task InitializeAsync_WithCsprojFile_LoadsSuccessfully() if (!File.Exists(csprojPath)) { // Skip test if project file not found + Assert.Ignore("Project file not found"); return; } @@ -125,10 +129,10 @@ public async Task InitializeAsync_WithCsprojFile_LoadsSuccessfully() var health = workspace.GetHealth(); // Assert - Assert.True(health.IsInitialized, "Workspace should be initialized from .csproj file"); - Assert.True(health.LoadedProjects > 0, "At least one project should be loaded"); - Assert.True(health.TotalFiles > 0, "Should have source files"); - Assert.True(health.ErrorCount < 50, + Assert.That(health.IsInitialized, Is.True, "Workspace should be initialized from .csproj file"); + Assert.That(health.LoadedProjects > 0, Is.True, "At least one project should be loaded"); + Assert.That(health.TotalFiles > 0, Is.True, "Should have source files"); + Assert.That(health.ErrorCount < 50, Is.True, $"Error count should be low (< 50), but got {health.ErrorCount}"); workspace.Dispose(); diff --git a/tests/MCPsharp.Tests/Services/SearchServiceTests.cs b/tests/MCPsharp.Tests/Services/SearchServiceTests.cs index 741dc3a..25d3c25 100644 --- a/tests/MCPsharp.Tests/Services/SearchServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/SearchServiceTests.cs @@ -6,17 +6,18 @@ using MCPsharp.Models.Search; using MCPsharp.Services; using Microsoft.Extensions.Logging.Abstractions; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; -public class SearchServiceTests : IDisposable +public class SearchServiceTests { - private readonly string _testDirectory; - private readonly ProjectContextManager _projectContext; - private readonly SearchService _searchService; + private string _testDirectory = null!; + private ProjectContextManager _projectContext = null!; + private SearchService _searchService = null!; - public SearchServiceTests() + [SetUp] + public void SetUp() { // Create a temporary test directory _testDirectory = Path.Combine(Path.GetTempPath(), $"SearchServiceTests_{Guid.NewGuid()}"); @@ -30,7 +31,8 @@ public SearchServiceTests() _searchService = new SearchService(_projectContext, NullLogger.Instance); } - public void Dispose() + [TearDown] + public void TearDown() { // Clean up test directory if (Directory.Exists(_testDirectory)) @@ -39,7 +41,7 @@ public void Dispose() } } - [Fact] + [Test] public async Task SearchTextAsync_EmptyPattern_ReturnsError() { // Arrange @@ -49,11 +51,11 @@ public async Task SearchTextAsync_EmptyPattern_ReturnsError() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.False(result.Success); - Assert.Contains("empty", result.ErrorMessage ?? "", StringComparison.OrdinalIgnoreCase); + Assert.That(result.Success, Is.False); + Assert.That(result.ErrorMessage ?? "", Does.Contain("empty").IgnoreCase); } - [Fact] + [Test] public async Task SearchTextAsync_NonExistentDirectory_ReturnsError() { // Arrange @@ -67,11 +69,11 @@ public async Task SearchTextAsync_NonExistentDirectory_ReturnsError() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.False(result.Success); - Assert.Contains("does not exist", result.ErrorMessage ?? "", StringComparison.OrdinalIgnoreCase); + Assert.That(result.Success, Is.False); + Assert.That(result.ErrorMessage ?? "", Does.Contain("does not exist").IgnoreCase); } - [Fact] + [Test] public async Task SearchTextAsync_LiteralSearch_FindsMatches() { // Arrange @@ -88,12 +90,12 @@ public async Task SearchTextAsync_LiteralSearch_FindsMatches() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Equal(2, result.TotalMatches); - Assert.All(result.Matches, m => Assert.Equal(1, m.LineNumber)); + Assert.That(result.Success, Is.True); + Assert.That(result.TotalMatches, Is.EqualTo(2)); + Assert.That(result.Matches, Has.All.Matches(m => m.LineNumber == 1)); } - [Fact] + [Test] public async Task SearchTextAsync_CaseInsensitive_FindsMatches() { // Arrange @@ -109,11 +111,11 @@ public async Task SearchTextAsync_CaseInsensitive_FindsMatches() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Equal(2, result.TotalMatches); + Assert.That(result.Success, Is.True); + Assert.That(result.TotalMatches, Is.EqualTo(2)); } - [Fact] + [Test] public async Task SearchTextAsync_RegexSearch_FindsMatches() { // Arrange @@ -129,11 +131,11 @@ public async Task SearchTextAsync_RegexSearch_FindsMatches() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Equal(3, result.TotalMatches); + Assert.That(result.Success, Is.True); + Assert.That(result.TotalMatches, Is.EqualTo(3)); } - [Fact] + [Test] public async Task SearchTextAsync_InvalidRegex_ReturnsError() { // Arrange @@ -148,12 +150,12 @@ public async Task SearchTextAsync_InvalidRegex_ReturnsError() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.NotNull(result); - Assert.False(result.Success); - Assert.Contains("Invalid regex", result.ErrorMessage ?? "", StringComparison.OrdinalIgnoreCase); + Assert.That(result, Is.Not.Null); + Assert.That(result.Success, Is.False); + Assert.That(result.ErrorMessage ?? "", Does.Contain("Invalid regex").IgnoreCase); } - [Fact] + [Test] public async Task SearchTextAsync_IncludePattern_FiltersFiles() { // Arrange @@ -171,12 +173,12 @@ public async Task SearchTextAsync_IncludePattern_FiltersFiles() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Equal(1, result.TotalMatches); - Assert.EndsWith(".cs", result.Matches[0].FilePath); + Assert.That(result.Success, Is.True); + Assert.That(result.TotalMatches, Is.EqualTo(1)); + Assert.That(result.Matches[0].FilePath, Does.EndWith(".cs")); } - [Fact] + [Test] public async Task SearchTextAsync_ExcludePattern_FiltersFiles() { // Arrange @@ -193,12 +195,12 @@ public async Task SearchTextAsync_ExcludePattern_FiltersFiles() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Equal(1, result.TotalMatches); - Assert.DoesNotContain("ignore", result.Matches[0].FilePath, StringComparison.OrdinalIgnoreCase); + Assert.That(result.Success, Is.True); + Assert.That(result.TotalMatches, Is.EqualTo(1)); + Assert.That(result.Matches[0].FilePath, Does.Not.Contain("ignore").IgnoreCase); } - [Fact] + [Test] public async Task SearchTextAsync_ContextLines_IncludesContext() { // Arrange @@ -214,18 +216,18 @@ public async Task SearchTextAsync_ContextLines_IncludesContext() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Single(result.Matches); + Assert.That(result.Success, Is.True); + Assert.That(result.Matches, Has.Count.EqualTo(1)); var match = result.Matches[0]; - Assert.Equal(2, match.ContextBefore.Count); - Assert.Equal("line 1", match.ContextBefore[0]); - Assert.Equal("line 2", match.ContextBefore[1]); - Assert.Equal(2, match.ContextAfter.Count); - Assert.Equal("line 4", match.ContextAfter[0]); - Assert.Equal("line 5", match.ContextAfter[1]); + Assert.That(match.ContextBefore, Has.Count.EqualTo(2)); + Assert.That(match.ContextBefore[0], Is.EqualTo("line 1")); + Assert.That(match.ContextBefore[1], Is.EqualTo("line 2")); + Assert.That(match.ContextAfter, Has.Count.EqualTo(2)); + Assert.That(match.ContextAfter[0], Is.EqualTo("line 4")); + Assert.That(match.ContextAfter[1], Is.EqualTo("line 5")); } - [Fact] + [Test] public async Task SearchTextAsync_ContextLines_HandlesFileBoundaries() { // Arrange @@ -241,13 +243,13 @@ public async Task SearchTextAsync_ContextLines_HandlesFileBoundaries() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); + Assert.That(result.Success, Is.True); var match = result.Matches[0]; - Assert.Empty(match.ContextBefore); // No lines before - Assert.Single(match.ContextAfter); // Only one line after + Assert.That(match.ContextBefore, Is.Empty); // No lines before + Assert.That(match.ContextAfter, Has.Count.EqualTo(1)); // Only one line after } - [Fact] + [Test] public async Task SearchTextAsync_Pagination_ReturnsCorrectSubset() { // Arrange @@ -265,15 +267,15 @@ public async Task SearchTextAsync_Pagination_ReturnsCorrectSubset() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Equal(50, result.TotalMatches); - Assert.Equal(10, result.Returned); - Assert.Equal(5, result.Offset); - Assert.True(result.HasMore); - Assert.Equal(6, result.Matches[0].LineNumber); // First match should be line 6 (offset 5) + Assert.That(result.Success, Is.True); + Assert.That(result.TotalMatches, Is.EqualTo(50)); + Assert.That(result.Returned, Is.EqualTo(10)); + Assert.That(result.Offset, Is.EqualTo(5)); + Assert.That(result.HasMore, Is.True); + Assert.That(result.Matches[0].LineNumber, Is.EqualTo(6)); // First match should be line 6 (offset 5) } - [Fact] + [Test] public async Task SearchTextAsync_NoMatches_ReturnsEmptyResult() { // Arrange @@ -288,13 +290,13 @@ public async Task SearchTextAsync_NoMatches_ReturnsEmptyResult() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Equal(0, result.TotalMatches); - Assert.Empty(result.Matches); - Assert.False(result.HasMore); + Assert.That(result.Success, Is.True); + Assert.That(result.TotalMatches, Is.EqualTo(0)); + Assert.That(result.Matches, Is.Empty); + Assert.That(result.HasMore, Is.False); } - [Fact] + [Test] public async Task SearchTextAsync_SkipsBinaryFiles() { // Arrange @@ -310,12 +312,12 @@ public async Task SearchTextAsync_SkipsBinaryFiles() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); + Assert.That(result.Success, Is.True); // Should only find match in .cs file, not .dll - Assert.All(result.Matches, m => Assert.EndsWith(".cs", m.FilePath)); + Assert.That(result.Matches, Has.All.Matches(m => m.FilePath.EndsWith(".cs"))); } - [Fact] + [Test] public async Task SearchTextAsync_SkipsDefaultExcludeDirs() { // Arrange @@ -333,12 +335,12 @@ public async Task SearchTextAsync_SkipsDefaultExcludeDirs() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); + Assert.That(result.Success, Is.True); // Should not find matches in bin directory - Assert.All(result.Matches, m => Assert.DoesNotContain("bin", m.FilePath)); + Assert.That(result.Matches, Has.All.Matches(m => !m.FilePath.Contains("bin"))); } - [Fact] + [Test] public async Task SearchTextAsync_ColumnNumber_IsCorrect() { // Arrange @@ -353,12 +355,12 @@ public async Task SearchTextAsync_ColumnNumber_IsCorrect() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Single(result.Matches); - Assert.Equal(5, result.Matches[0].ColumnNumber); // 1-based, after 4 spaces + Assert.That(result.Success, Is.True); + Assert.That(result.Matches, Has.Count.EqualTo(1)); + Assert.That(result.Matches[0].ColumnNumber, Is.EqualTo(5)); // 1-based, after 4 spaces } - [Fact] + [Test] public async Task SearchTextAsync_MultipleMatchesInSameLine_FindsAll() { // Arrange @@ -373,13 +375,13 @@ public async Task SearchTextAsync_MultipleMatchesInSameLine_FindsAll() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); + Assert.That(result.Success, Is.True); // Note: Current implementation finds first match per line // This test documents expected behavior - Assert.Equal(1, result.TotalMatches); + Assert.That(result.TotalMatches, Is.EqualTo(1)); } - [Fact] + [Test] public async Task SearchTextAsync_CancellationToken_CancelsOperation() { // Arrange @@ -397,11 +399,11 @@ public async Task SearchTextAsync_CancellationToken_CancelsOperation() }; // Act & Assert - await Assert.ThrowsAsync( + Assert.ThrowsAsync( async () => await _searchService.SearchTextAsync(request, cts.Token)); } - [Fact] + [Test] public async Task SearchTextAsync_PerformanceTest_SearchesQuickly() { // Arrange @@ -419,12 +421,12 @@ public async Task SearchTextAsync_PerformanceTest_SearchesQuickly() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Equal(100, result.TotalMatches); - Assert.True(result.SearchDurationMs < 3000, $"Search took {result.SearchDurationMs}ms, expected < 3000ms"); + Assert.That(result.Success, Is.True); + Assert.That(result.TotalMatches, Is.EqualTo(100)); + Assert.That(result.SearchDurationMs, Is.LessThan(3000), $"Search took {result.SearchDurationMs}ms, expected < 3000ms"); } - [Fact] + [Test] public async Task SearchTextAsync_RegexWithGroups_CapturesMatch() { // Arrange @@ -440,9 +442,9 @@ public async Task SearchTextAsync_RegexWithGroups_CapturesMatch() var result = await _searchService.SearchTextAsync(request); // Assert - Assert.True(result.Success); - Assert.Single(result.Matches); - Assert.Contains("1.2.3", result.Matches[0].MatchText); + Assert.That(result.Success, Is.True); + Assert.That(result.Matches, Has.Count.EqualTo(1)); + Assert.That(result.Matches[0].MatchText, Does.Contain("1.2.3")); } private void CreateTestFile(string relativePath, string content) diff --git a/tests/MCPsharp.Tests/Services/Streaming/StreamingFileProcessorTests.cs b/tests/MCPsharp.Tests/Services/Streaming/StreamingFileProcessorTests.cs index 0bab67f..20b3726 100644 --- a/tests/MCPsharp.Tests/Services/Streaming/StreamingFileProcessorTests.cs +++ b/tests/MCPsharp.Tests/Services/Streaming/StreamingFileProcessorTests.cs @@ -178,7 +178,7 @@ public async Task ProcessFileAsync_WithProgressReporting_ShouldReportProgress() { // If progress was reported, verify it's in order Assert.That(progressReports, Is.Ordered.By("ProgressPercentage").Ascending); - Assert.NotNull(progressReports.LastOrDefault()); + Assert.That(progressReports.LastOrDefault(), Is.Not.Null); Assert.That(progressReports.Last().ProgressPercentage, Is.EqualTo(100)); } } @@ -236,7 +236,7 @@ public async Task ProcessMultipleFilesAsync_WithValidFiles_ShouldProcessAll() } // Assert - Assert.NotNull(results); + Assert.That(results, Is.Not.Null); if (results == null) throw new InvalidOperationException("Results should not be null"); Assert.That(results.Count, Is.EqualTo(3)); @@ -597,4 +597,11 @@ public async Task ProcessFileAsync_WithSameFile_ShouldProduceConsistentResults() Assert.That(result1.OriginalSize, Is.EqualTo(result2.OriginalSize)); Assert.That(result1.ProcessedSize, Is.EqualTo(result2.ProcessedSize)); } + + [TearDown] + protected override void TearDown() + { + _processor?.Dispose(); + base.TearDown(); + } } \ No newline at end of file diff --git a/tests/MCPsharp.Tests/Services/TypeUsageServiceTests.cs b/tests/MCPsharp.Tests/Services/TypeUsageServiceTests.cs index 9429032..c19bc45 100644 --- a/tests/MCPsharp.Tests/Services/TypeUsageServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/TypeUsageServiceTests.cs @@ -3,20 +3,22 @@ using MCPsharp.Models.Roslyn; using MCPsharp.Services.Roslyn; using MCPsharp.Tests.TestFixtures; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; /// /// Unit tests for TypeUsageService /// -public class TypeUsageServiceTests : IDisposable +[TestFixture] +public class TypeUsageServiceTests { - private readonly RoslynWorkspace _workspace; - private readonly SymbolQueryService _symbolQuery; - private readonly TypeUsageService _typeUsage; + private RoslynWorkspace _workspace; + private SymbolQueryService _symbolQuery; + private TypeUsageService _typeUsage; - public TypeUsageServiceTests() + [SetUp] + public void SetUp() { _workspace = new RoslynWorkspace(); _symbolQuery = new SymbolQueryService(_workspace); @@ -185,143 +187,143 @@ public override string GetName() } } - [Fact] + [Test] public async Task FindTypeUsages_ShouldFindAllUsages() { // Act var result = await _typeUsage.FindTypeUsagesAsync("Service"); // Assert - Assert.NotNull(result); - Assert.Equal("Service", result.TypeName); - Assert.True(result.TotalUsages >= 0); // Allow for 0 if symbol finding fails + Assert.That(result, Is.Not.Null); + Assert.That(result.TypeName, Is.EqualTo("Service")); + Assert.That(result.TotalUsages, Is.GreaterThanOrEqualTo(0)); // Allow for 0 if symbol finding fails if (result.TotalUsages > 0) { - Assert.Contains(result.Usages, u => u.UsageKind == TypeUsageKind.TypeDeclaration); + Assert.That(result.Usages, Has.Some.Property("UsageKind").EqualTo(TypeUsageKind.TypeDeclaration)); } } - [Fact] + [Test] public async Task FindTypeUsagesByFullName_ShouldFindExactMatch() { // Act var result = await _typeUsage.FindTypeUsagesByFullNameAsync("MCPsharp.Tests.TestFixtures.Service"); // Assert - Assert.NotNull(result); - Assert.Equal("MCPsharp.Tests.TestFixtures.Service", result.FullTypeName); - Assert.True(result.TotalUsages >= 0); // Allow for 0 if symbol finding fails + Assert.That(result, Is.Not.Null); + Assert.That(result.FullTypeName, Is.EqualTo("MCPsharp.Tests.TestFixtures.Service")); + Assert.That(result.TotalUsages, Is.GreaterThanOrEqualTo(0)); // Allow for 0 if symbol finding fails } - [Fact] + [Test] public async Task FindInstantiations_ShouldFindOnlyInstantiations() { // Act var result = await _typeUsage.FindInstantiationsAsync("Service"); // Assert - Assert.NotNull(result); - Assert.All(result, u => Assert.Equal(TypeUsageKind.Instantiation, u.UsageKind)); + Assert.That(result, Is.Not.Null); + Assert.That(result, Has.All.Property("UsageKind").EqualTo(TypeUsageKind.Instantiation)); } - [Fact] + [Test] public async Task AnalyzeInheritance_ShouldAnalyzeInheritance() { // Act var result = await _typeUsage.AnalyzeInheritanceAsync("DerivedClass"); // Assert - Assert.NotNull(result); - Assert.Equal("DerivedClass", result.TargetType); - Assert.True(result.BaseClasses.Count >= 0); // Allow for 0 if inheritance analysis fails + Assert.That(result, Is.Not.Null); + Assert.That(result.TargetType, Is.EqualTo("DerivedClass")); + Assert.That(result.BaseClasses.Count, Is.GreaterThanOrEqualTo(0)); // Allow for 0 if inheritance analysis fails if (result.BaseClasses.Count > 0) { - Assert.Contains(result.BaseClasses, b => b.UsageKind == TypeUsageKind.BaseClass); + Assert.That(result.BaseClasses, Has.Some.Property("UsageKind").EqualTo(TypeUsageKind.BaseClass)); } } - [Fact] + [Test] public async Task AnalyzeInheritance_ForInterface_ShouldAnalyzeInterface() { // Act var result = await _typeUsage.AnalyzeInheritanceAsync("IService"); // Assert - Assert.NotNull(result); - Assert.Equal("IService", result.TargetType); - Assert.True(result.IsInterface); - Assert.True(result.InterfaceImplementations.Count >= 0); // Allow for 0 if implementation analysis fails + Assert.That(result, Is.Not.Null); + Assert.That(result.TargetType, Is.EqualTo("IService")); + Assert.That(result.IsInterface, Is.True); + Assert.That(result.InterfaceImplementations.Count, Is.GreaterThanOrEqualTo(0)); // Allow for 0 if implementation analysis fails } - [Fact] + [Test] public async Task FindInterfaceImplementations_ShouldFindImplementations() { // Act var result = await _typeUsage.FindInterfaceImplementationsAsync("IService"); // Assert - Assert.NotNull(result); - Assert.All(result, u => Assert.Equal(TypeUsageKind.InterfaceImplementation, u.UsageKind)); + Assert.That(result, Is.Not.Null); + Assert.That(result, Has.All.Property("UsageKind").EqualTo(TypeUsageKind.InterfaceImplementation)); } - [Fact] + [Test] public async Task FindGenericUsages_ShouldFindGenericUsages() { // Act var result = await _typeUsage.FindGenericUsagesAsync("GenericService"); // Assert - Assert.NotNull(result); + Assert.That(result, Is.Not.Null); // May contain generic argument usages } - [Fact] + [Test] public async Task AnalyzeTypeDependencies_ShouldAnalyzeDependencies() { // Act var result = await _typeUsage.AnalyzeTypeDependenciesAsync("Consumer"); // Assert - Assert.NotNull(result); - Assert.Equal("Consumer", result.TargetType); - Assert.True(result.TotalDependencies >= 0); + Assert.That(result, Is.Not.Null); + Assert.That(result.TargetType, Is.EqualTo("Consumer")); + Assert.That(result.TotalDependencies, Is.GreaterThanOrEqualTo(0)); } - [Fact] + [Test] public async Task AnalyzeUsagePatterns_ShouldAnalyzePatterns() { // Act var result = await _typeUsage.AnalyzeUsagePatternsAsync("MCPsharp.Tests.TestFixtures"); // Assert - Assert.NotNull(result); - Assert.True(result.TypeStatistics.Count >= 0); // Allow for 0 if pattern analysis fails - Assert.True(result.TotalTypesAnalyzed >= 0); + Assert.That(result, Is.Not.Null); + Assert.That(result.TypeStatistics.Count, Is.GreaterThanOrEqualTo(0)); // Allow for 0 if pattern analysis fails + Assert.That(result.TotalTypesAnalyzed, Is.GreaterThanOrEqualTo(0)); } - [Fact] + [Test] public async Task FindRefactoringOpportunities_ShouldFindOpportunities() { // Act var result = await _typeUsage.FindRefactoringOpportunitiesAsync("MCPsharp.Tests.TestFixtures"); // Assert - Assert.NotNull(result); - Assert.True(result.TotalOpportunities >= 0); - Assert.NotNull(result.OpportunityBreakdown); + Assert.That(result, Is.Not.Null); + Assert.That(result.TotalOpportunities, Is.GreaterThanOrEqualTo(0)); + Assert.That(result.OpportunityBreakdown, Is.Not.Null); } - [Fact] + [Test] public async Task FindTypeUsages_WithNonExistentType_ShouldReturnNull() { // Act var result = await _typeUsage.FindTypeUsagesAsync("NonExistentType"); // Assert - Assert.Null(result); + Assert.That(result, Is.Null); } - [Fact] + [Test] public async Task FindTypeUsagesAtLocation_ShouldFindTypeAtLocation() { // This test would require more setup to get actual file locations @@ -329,10 +331,10 @@ public async Task FindTypeUsagesAtLocation_ShouldFindTypeAtLocation() var result = await _typeUsage.FindTypeUsagesAtLocationAsync("TestFile.cs", 10, 5); // Should return null for non-existent file/location - Assert.Null(result); + Assert.That(result, Is.Null); } - [Fact] + [Test] public void TypeUsageInfo_ShouldGenerateCorrectDescription() { // Arrange @@ -353,12 +355,12 @@ public void TypeUsageInfo_ShouldGenerateCorrectDescription() var description = usage.GetDescription(); // Assert - Assert.Contains("instantiation", description.ToLower()); - Assert.Contains("testmethod", description.ToLower()); - Assert.Contains("testclass", description.ToLower()); + Assert.That(description.ToLower(), Does.Contain("instantiation")); + Assert.That(description.ToLower(), Does.Contain("testmethod")); + Assert.That(description.ToLower(), Does.Contain("testclass")); } - [Fact] + [Test] public void TypeUsageInfo_WithGeneric_ShouldIncludeGenericInfo() { // Arrange @@ -378,11 +380,11 @@ public void TypeUsageInfo_WithGeneric_ShouldIncludeGenericInfo() var description = usage.GetDescription(); // Assert - Assert.Contains("generic", description.ToLower()); - Assert.Contains("string", description); + Assert.That(description.ToLower(), Does.Contain("generic")); + Assert.That(description, Does.Contain("string")); } - [Fact] + [Test] public void InheritanceAnalysis_ShouldCalculateCorrectProperties() { // Arrange @@ -423,14 +425,14 @@ public void InheritanceAnalysis_ShouldCalculateCorrectProperties() }; // Assert - Assert.Equal("DerivedClass", analysis.TargetType); - Assert.Single(analysis.BaseClasses); - Assert.Single(analysis.DerivedClasses); - Assert.Equal(1, analysis.InheritanceDepth); - Assert.Equal(2, analysis.InheritanceChain.Count); + Assert.That(analysis.TargetType, Is.EqualTo("DerivedClass")); + Assert.That(analysis.BaseClasses, Has.Count.EqualTo(1)); + Assert.That(analysis.DerivedClasses, Has.Count.EqualTo(1)); + Assert.That(analysis.InheritanceDepth, Is.EqualTo(1)); + Assert.That(analysis.InheritanceChain.Count, Is.EqualTo(2)); } - [Fact] + [Test] public void TypeDependencyAnalysis_ShouldCalculateCorrectProperties() { // Arrange @@ -459,13 +461,13 @@ public void TypeDependencyAnalysis_ShouldCalculateCorrectProperties() }; // Assert - Assert.Equal("Service", analysis.TargetType); - Assert.Single(analysis.Dependencies); - Assert.Equal(1, analysis.TotalDependencies); - Assert.False(analysis.HasCircularDependencies); + Assert.That(analysis.TargetType, Is.EqualTo("Service")); + Assert.That(analysis.Dependencies, Has.Count.EqualTo(1)); + Assert.That(analysis.TotalDependencies, Is.EqualTo(1)); + Assert.That(analysis.HasCircularDependencies, Is.False); } - [Fact] + [Test] public void TypeRefactoringOpportunities_ShouldCalculateCorrectBreakdown() { // Arrange @@ -489,14 +491,15 @@ public void TypeRefactoringOpportunities_ShouldCalculateCorrectBreakdown() }; // Assert - Assert.Equal(1, opportunities.TotalOpportunities); - Assert.Single(opportunities.UnusedTypes); - Assert.True(opportunities.OpportunityBreakdown.ContainsKey("Unused Types")); - Assert.Equal(1, opportunities.OpportunityBreakdown["Unused Types"]); + Assert.That(opportunities.TotalOpportunities, Is.EqualTo(1)); + Assert.That(opportunities.UnusedTypes, Has.Count.EqualTo(1)); + Assert.That(opportunities.OpportunityBreakdown.ContainsKey("Unused Types"), Is.True); + Assert.That(opportunities.OpportunityBreakdown["Unused Types"], Is.EqualTo(1)); } - public void Dispose() + [TearDown] + public void TearDown() { - // RoslynWorkspace no longer implements IDisposable + _workspace?.Dispose(); } -} \ No newline at end of file +} diff --git a/tests/MCPsharp.Tests/Services/WorkflowAnalyzerServiceTests.cs b/tests/MCPsharp.Tests/Services/WorkflowAnalyzerServiceTests.cs index 8686955..df4cbef 100644 --- a/tests/MCPsharp.Tests/Services/WorkflowAnalyzerServiceTests.cs +++ b/tests/MCPsharp.Tests/Services/WorkflowAnalyzerServiceTests.cs @@ -1,6 +1,6 @@ using MCPsharp.Models; using MCPsharp.Services; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests.Services; @@ -15,7 +15,7 @@ public WorkflowAnalyzerServiceTests() _testDataPath = Path.Combine(Directory.GetCurrentDirectory(), "TestData", "Workflows"); } - [Fact] + [Test] public async Task FindWorkflowsAsync_WithNoWorkflowsDirectory_ReturnsEmptyList() { // Arrange @@ -25,10 +25,10 @@ public async Task FindWorkflowsAsync_WithNoWorkflowsDirectory_ReturnsEmptyList() var result = await _service.FindWorkflowsAsync(nonExistentPath); // Assert - Assert.Empty(result); + Assert.That(result, Is.Empty); } - [Fact] + [Test] public async Task FindWorkflowsAsync_WithWorkflowsDirectory_ReturnsWorkflowFiles() { // Arrange @@ -46,8 +46,8 @@ public async Task FindWorkflowsAsync_WithWorkflowsDirectory_ReturnsWorkflowFiles var result = await _service.FindWorkflowsAsync(tempPath); // Assert - Assert.Equal(2, result.Count); - Assert.All(result, path => Assert.True(path.EndsWith(".yml") || path.EndsWith(".yaml"))); + Assert.That(result, Has.Count.EqualTo(2)); + Assert.That(result, Has.All.Matches(path => path.EndsWith(".yml") || path.EndsWith(".yaml"))); } finally { @@ -55,7 +55,7 @@ public async Task FindWorkflowsAsync_WithWorkflowsDirectory_ReturnsWorkflowFiles } } - [Fact] + [Test] public async Task ParseWorkflowAsync_WithValidWorkflow_ParsesCorrectly() { // Arrange @@ -65,36 +65,36 @@ public async Task ParseWorkflowAsync_WithValidWorkflow_ParsesCorrectly() var result = await _service.ParseWorkflowAsync(workflowPath); // Assert - Assert.Equal("Build", result.Name); - Assert.Equal(workflowPath, result.FilePath); - Assert.NotNull(result.Triggers); - Assert.Contains("push", result.Triggers); - Assert.Contains("pull_request", result.Triggers); + Assert.That(result.Name, Is.EqualTo("Build")); + Assert.That(result.FilePath, Is.EqualTo(workflowPath)); + Assert.That(result.Triggers, Is.Not.Null); + Assert.That(result.Triggers, Does.Contain("push")); + Assert.That(result.Triggers, Does.Contain("pull_request")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_WithNonExistentFile_ThrowsFileNotFoundException() { // Arrange var nonExistentPath = Path.Combine(_testDataPath, "nonexistent.yml"); // Act & Assert - await Assert.ThrowsAsync( + Assert.ThrowsAsync( async () => await _service.ParseWorkflowAsync(nonExistentPath)); } - [Fact] + [Test] public async Task ParseWorkflowAsync_WithInvalidYaml_ThrowsException() { // Arrange var invalidPath = Path.Combine(_testDataPath, "invalid.yml"); // Act & Assert - await Assert.ThrowsAsync( + Assert.ThrowsAsync( async () => await _service.ParseWorkflowAsync(invalidPath)); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsTriggers_FromSimpleList() { // Arrange @@ -104,13 +104,13 @@ public async Task ParseWorkflowAsync_ExtractsTriggers_FromSimpleList() var result = await _service.ParseWorkflowAsync(workflowPath); // Assert - Assert.NotNull(result.Triggers); - Assert.Equal(2, result.Triggers.Count); - Assert.Contains("push", result.Triggers); - Assert.Contains("pull_request", result.Triggers); + Assert.That(result.Triggers, Is.Not.Null); + Assert.That(result.Triggers, Has.Count.EqualTo(2)); + Assert.That(result.Triggers, Does.Contain("push")); + Assert.That(result.Triggers, Does.Contain("pull_request")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsTriggers_FromDictionary() { // Arrange @@ -120,12 +120,12 @@ public async Task ParseWorkflowAsync_ExtractsTriggers_FromDictionary() var result = await _service.ParseWorkflowAsync(workflowPath); // Assert - Assert.NotNull(result.Triggers); - Assert.Contains("push", result.Triggers); - Assert.Contains("pull_request", result.Triggers); + Assert.That(result.Triggers, Is.Not.Null); + Assert.That(result.Triggers, Does.Contain("push")); + Assert.That(result.Triggers, Does.Contain("pull_request")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsEnvironmentVariables() { // Arrange @@ -135,12 +135,12 @@ public async Task ParseWorkflowAsync_ExtractsEnvironmentVariables() var result = await _service.ParseWorkflowAsync(workflowPath); // Assert - Assert.NotNull(result.Environment); - Assert.Contains("DOTNET_VERSION", result.Environment.Keys); - Assert.Equal("9.0.x", result.Environment["DOTNET_VERSION"]); + Assert.That(result.Environment, Is.Not.Null); + Assert.That(result.Environment.Keys, Does.Contain("DOTNET_VERSION")); + Assert.That(result.Environment["DOTNET_VERSION"], Is.EqualTo("9.0.x")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsJobs() { // Arrange @@ -150,13 +150,13 @@ public async Task ParseWorkflowAsync_ExtractsJobs() var result = await _service.ParseWorkflowAsync(workflowPath); // Assert - Assert.NotNull(result.Jobs); - Assert.Single(result.Jobs); - Assert.Equal("build", result.Jobs[0].Name); - Assert.Equal("ubuntu-latest", result.Jobs[0].RunsOn); + Assert.That(result.Jobs, Is.Not.Null); + Assert.That(result.Jobs, Has.Count.EqualTo(1)); + Assert.That(result.Jobs[0].Name, Is.EqualTo("build")); + Assert.That(result.Jobs[0].RunsOn, Is.EqualTo("ubuntu-latest")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsSteps() { // Arrange @@ -167,26 +167,26 @@ public async Task ParseWorkflowAsync_ExtractsSteps() // Assert var job = result.Jobs?.FirstOrDefault(); - Assert.NotNull(job); - Assert.NotNull(job.Steps); - Assert.Equal(4, job.Steps.Count); + Assert.That(job, Is.Not.Null); + Assert.That(job.Steps, Is.Not.Null); + Assert.That(job.Steps, Has.Count.EqualTo(4)); var checkoutStep = job.Steps[0]; - Assert.Equal("actions/checkout@v4", checkoutStep.Uses); + Assert.That(checkoutStep.Uses, Is.EqualTo("actions/checkout@v4")); var setupDotnetStep = job.Steps[1]; - Assert.Equal("actions/setup-dotnet@v4", setupDotnetStep.Uses); - Assert.NotNull(setupDotnetStep.With); - Assert.Equal("9.0.x", setupDotnetStep.With["dotnet-version"]); + Assert.That(setupDotnetStep.Uses, Is.EqualTo("actions/setup-dotnet@v4")); + Assert.That(setupDotnetStep.With, Is.Not.Null); + Assert.That(setupDotnetStep.With["dotnet-version"], Is.EqualTo("9.0.x")); var buildStep = job.Steps[2]; - Assert.Equal("dotnet build", buildStep.Run); + Assert.That(buildStep.Run, Is.EqualTo("dotnet build")); var testStep = job.Steps[3]; - Assert.Equal("dotnet test", testStep.Run); + Assert.That(testStep.Run, Is.EqualTo("dotnet test")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsSecrets() { // Arrange @@ -196,13 +196,13 @@ public async Task ParseWorkflowAsync_ExtractsSecrets() var result = await _service.ParseWorkflowAsync(workflowPath); // Assert - Assert.NotNull(result.Secrets); - Assert.Equal(2, result.Secrets.Count); - Assert.Contains("NUGET_API_KEY", result.Secrets); - Assert.Contains("DEPLOY_TOKEN", result.Secrets); + Assert.That(result.Secrets, Is.Not.Null); + Assert.That(result.Secrets, Has.Count.EqualTo(2)); + Assert.That(result.Secrets, Does.Contain("NUGET_API_KEY")); + Assert.That(result.Secrets, Does.Contain("DEPLOY_TOKEN")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsJobLevelEnvironment() { // Arrange @@ -213,13 +213,13 @@ public async Task ParseWorkflowAsync_ExtractsJobLevelEnvironment() // Assert var job = result.Jobs?.FirstOrDefault(); - Assert.NotNull(job); - Assert.NotNull(job.Environment); - Assert.Contains("DEPLOY_ENV", job.Environment.Keys); - Assert.Equal("production", job.Environment["DEPLOY_ENV"]); + Assert.That(job, Is.Not.Null); + Assert.That(job.Environment, Is.Not.Null); + Assert.That(job.Environment.Keys, Does.Contain("DEPLOY_ENV")); + Assert.That(job.Environment["DEPLOY_ENV"], Is.EqualTo("production")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_WithNamedSteps_ExtractsStepNames() { // Arrange @@ -230,18 +230,18 @@ public async Task ParseWorkflowAsync_WithNamedSteps_ExtractsStepNames() // Assert var job = result.Jobs?.FirstOrDefault(); - Assert.NotNull(job); - Assert.NotNull(job.Steps); + Assert.That(job, Is.Not.Null); + Assert.That(job.Steps, Is.Not.Null); var checkoutStep = job.Steps.FirstOrDefault(s => s.Name == "Checkout code"); - Assert.NotNull(checkoutStep); - Assert.Equal("actions/checkout@v4", checkoutStep.Uses); + Assert.That(checkoutStep, Is.Not.Null); + Assert.That(checkoutStep.Uses, Is.EqualTo("actions/checkout@v4")); var setupStep = job.Steps.FirstOrDefault(s => s.Name == "Setup .NET"); - Assert.NotNull(setupStep); + Assert.That(setupStep, Is.Not.Null); } - [Fact] + [Test] public async Task GetAllWorkflowsAsync_ReturnsAllValidWorkflows() { // Arrange @@ -259,9 +259,9 @@ public async Task GetAllWorkflowsAsync_ReturnsAllValidWorkflows() var result = await _service.GetAllWorkflowsAsync(tempPath); // Assert - should skip invalid.yml - Assert.Equal(2, result.Count); - Assert.Contains(result, w => w.Name == "Build"); - Assert.Contains(result, w => w.Name == "Deploy"); + Assert.That(result, Has.Count.EqualTo(2)); + Assert.That(result, Has.Some.Property("Name").EqualTo("Build")); + Assert.That(result, Has.Some.Property("Name").EqualTo("Deploy")); } finally { @@ -269,7 +269,7 @@ public async Task GetAllWorkflowsAsync_ReturnsAllValidWorkflows() } } - [Fact] + [Test] public async Task ValidateWorkflowConsistencyAsync_WithMatchingVersions_ReturnsNoIssues() { // Arrange @@ -314,10 +314,10 @@ public async Task ValidateWorkflowConsistencyAsync_WithMatchingVersions_ReturnsN var result = await _service.ValidateWorkflowConsistencyAsync(workflow, project); // Assert - Assert.Empty(result); + Assert.That(result, Is.Empty); } - [Fact] + [Test] public async Task ValidateWorkflowConsistencyAsync_WithMismatchedVersions_ReturnsWarning() { // Arrange @@ -362,14 +362,14 @@ public async Task ValidateWorkflowConsistencyAsync_WithMismatchedVersions_Return var result = await _service.ValidateWorkflowConsistencyAsync(workflow, project); // Assert - Assert.Single(result); - Assert.Equal("VersionMismatch", result[0].Type); - Assert.Equal("Warning", result[0].Severity); - Assert.Contains("8.0", result[0].Message); - Assert.Contains("net9.0", result[0].Message); + Assert.That(result, Has.Count.EqualTo(1)); + Assert.That(result[0].Type, Is.EqualTo("VersionMismatch")); + Assert.That(result[0].Severity, Is.EqualTo("Warning")); + Assert.That(result[0].Message, Does.Contain("8.0")); + Assert.That(result[0].Message, Does.Contain("net9.0")); } - [Fact] + [Test] public async Task ValidateWorkflowConsistencyAsync_WithMissingBuildSteps_ReturnsWarning() { // Arrange @@ -408,13 +408,13 @@ public async Task ValidateWorkflowConsistencyAsync_WithMissingBuildSteps_Returns var result = await _service.ValidateWorkflowConsistencyAsync(workflow, project); // Assert - Assert.Contains(result, issue => issue.Type == "MissingBuildStep"); + Assert.That(result, Has.Some.Property("Type").EqualTo("MissingBuildStep")); var buildStepIssue = result.First(issue => issue.Type == "MissingBuildStep"); - Assert.Equal("Warning", buildStepIssue.Severity); - Assert.Contains("dotnet build", buildStepIssue.Message); + Assert.That(buildStepIssue.Severity, Is.EqualTo("Warning")); + Assert.That(buildStepIssue.Message, Does.Contain("dotnet build")); } - [Fact] + [Test] public async Task ValidateWorkflowConsistencyAsync_WithLibraryProject_DoesNotRequireBuildSteps() { // Arrange @@ -453,6 +453,6 @@ public async Task ValidateWorkflowConsistencyAsync_WithLibraryProject_DoesNotReq var result = await _service.ValidateWorkflowConsistencyAsync(workflow, project); // Assert - Assert.DoesNotContain(result, issue => issue.Type == "MissingBuildStep"); + Assert.That(result, Has.None.Property("Type").EqualTo("MissingBuildStep")); } } diff --git a/tests/MCPsharp.Tests/WorkflowAnalyzerStandaloneTests.cs b/tests/MCPsharp.Tests/WorkflowAnalyzerStandaloneTests.cs index 3e4e9b9..55aa6e1 100644 --- a/tests/MCPsharp.Tests/WorkflowAnalyzerStandaloneTests.cs +++ b/tests/MCPsharp.Tests/WorkflowAnalyzerStandaloneTests.cs @@ -1,5 +1,5 @@ using MCPsharp.Services; -using Xunit; +using NUnit.Framework; namespace MCPsharp.Tests; @@ -7,12 +7,14 @@ namespace MCPsharp.Tests; /// Standalone tests for WorkflowAnalyzerService that don't depend on the main project building. /// These tests verify the core workflow parsing functionality in isolation. /// -public class WorkflowAnalyzerStandaloneTests : IDisposable +[TestFixture] +public class WorkflowAnalyzerStandaloneTests { - private readonly string _testWorkflowDir; - private readonly WorkflowAnalyzerService _service; + private string _testWorkflowDir; + private WorkflowAnalyzerService _service; - public WorkflowAnalyzerStandaloneTests() + [SetUp] + public void SetUp() { _service = new WorkflowAnalyzerService(); _testWorkflowDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), ".github", "workflows"); @@ -22,7 +24,8 @@ public WorkflowAnalyzerStandaloneTests() CreateTestWorkflows(); } - public void Dispose() + [TearDown] + public void TearDown() { var rootDir = Path.GetDirectoryName(Path.GetDirectoryName(_testWorkflowDir)); if (rootDir != null && Directory.Exists(rootDir)) @@ -73,130 +76,130 @@ private void CreateTestWorkflows() "); } - [Fact] + [Test] public async Task FindWorkflowsAsync_FindsYmlFiles() { var projectRoot = Path.GetDirectoryName(Path.GetDirectoryName(_testWorkflowDir))!; var workflows = await _service.FindWorkflowsAsync(projectRoot); - Assert.Equal(2, workflows.Count); - Assert.Contains(workflows, w => w.EndsWith("build.yml")); - Assert.Contains(workflows, w => w.EndsWith("deploy.yml")); + Assert.That(workflows.Count, Is.EqualTo(2)); + Assert.That(workflows, Has.Some.Matches(w => w.EndsWith("build.yml"))); + Assert.That(workflows, Has.Some.Matches(w => w.EndsWith("deploy.yml"))); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsBasicInfo() { var buildPath = Path.Combine(_testWorkflowDir, "build.yml"); var workflow = await _service.ParseWorkflowAsync(buildPath); - Assert.Equal("Build", workflow.Name); - Assert.Equal(buildPath, workflow.FilePath); + Assert.That(workflow.Name, Is.EqualTo("Build")); + Assert.That(workflow.FilePath, Is.EqualTo(buildPath)); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsTriggers() { var buildPath = Path.Combine(_testWorkflowDir, "build.yml"); var workflow = await _service.ParseWorkflowAsync(buildPath); - Assert.NotNull(workflow.Triggers); - Assert.Equal(2, workflow.Triggers.Count); - Assert.Contains("push", workflow.Triggers); - Assert.Contains("pull_request", workflow.Triggers); + Assert.That(workflow.Triggers, Is.Not.Null); + Assert.That(workflow.Triggers.Count, Is.EqualTo(2)); + Assert.That(workflow.Triggers, Does.Contain("push")); + Assert.That(workflow.Triggers, Does.Contain("pull_request")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsEnvironmentVariables() { var buildPath = Path.Combine(_testWorkflowDir, "build.yml"); var workflow = await _service.ParseWorkflowAsync(buildPath); - Assert.NotNull(workflow.Environment); - Assert.True(workflow.Environment.ContainsKey("DOTNET_VERSION")); - Assert.Equal("9.0.x", workflow.Environment["DOTNET_VERSION"]); + Assert.That(workflow.Environment, Is.Not.Null); + Assert.That(workflow.Environment.ContainsKey("DOTNET_VERSION"), Is.True); + Assert.That(workflow.Environment["DOTNET_VERSION"], Is.EqualTo("9.0.x")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsJobs() { var buildPath = Path.Combine(_testWorkflowDir, "build.yml"); var workflow = await _service.ParseWorkflowAsync(buildPath); - Assert.NotNull(workflow.Jobs); - Assert.Single(workflow.Jobs); + Assert.That(workflow.Jobs, Is.Not.Null); + Assert.That(workflow.Jobs, Has.Count.EqualTo(1)); var job = workflow.Jobs[0]; - Assert.Equal("build", job.Name); - Assert.Equal("ubuntu-latest", job.RunsOn); + Assert.That(job.Name, Is.EqualTo("build")); + Assert.That(job.RunsOn, Is.EqualTo("ubuntu-latest")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsSteps() { var buildPath = Path.Combine(_testWorkflowDir, "build.yml"); var workflow = await _service.ParseWorkflowAsync(buildPath); var job = workflow.Jobs![0]; - Assert.NotNull(job.Steps); - Assert.Equal(4, job.Steps.Count); + Assert.That(job.Steps, Is.Not.Null); + Assert.That(job.Steps.Count, Is.EqualTo(4)); - Assert.Equal("actions/checkout@v4", job.Steps[0].Uses); - Assert.Equal("actions/setup-dotnet@v4", job.Steps[1].Uses); - Assert.Equal("dotnet build", job.Steps[2].Run); - Assert.Equal("dotnet test", job.Steps[3].Run); + Assert.That(job.Steps[0].Uses, Is.EqualTo("actions/checkout@v4")); + Assert.That(job.Steps[1].Uses, Is.EqualTo("actions/setup-dotnet@v4")); + Assert.That(job.Steps[2].Run, Is.EqualTo("dotnet build")); + Assert.That(job.Steps[3].Run, Is.EqualTo("dotnet test")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsStepParameters() { var buildPath = Path.Combine(_testWorkflowDir, "build.yml"); var workflow = await _service.ParseWorkflowAsync(buildPath); var setupStep = workflow.Jobs![0].Steps![1]; - Assert.NotNull(setupStep.With); - Assert.True(setupStep.With.ContainsKey("dotnet-version")); - Assert.Equal("9.0.x", setupStep.With["dotnet-version"]); + Assert.That(setupStep.With, Is.Not.Null); + Assert.That(setupStep.With.ContainsKey("dotnet-version"), Is.True); + Assert.That(setupStep.With["dotnet-version"], Is.EqualTo("9.0.x")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsJobLevelEnvironment() { var deployPath = Path.Combine(_testWorkflowDir, "deploy.yml"); var workflow = await _service.ParseWorkflowAsync(deployPath); var job = workflow.Jobs![0]; - Assert.NotNull(job.Environment); - Assert.True(job.Environment.ContainsKey("DEPLOY_ENV")); - Assert.Equal("production", job.Environment["DEPLOY_ENV"]); + Assert.That(job.Environment, Is.Not.Null); + Assert.That(job.Environment.ContainsKey("DEPLOY_ENV"), Is.True); + Assert.That(job.Environment["DEPLOY_ENV"], Is.EqualTo("production")); } - [Fact] + [Test] public async Task ParseWorkflowAsync_ExtractsSecrets() { var deployPath = Path.Combine(_testWorkflowDir, "deploy.yml"); var workflow = await _service.ParseWorkflowAsync(deployPath); - Assert.NotNull(workflow.Secrets); - Assert.Single(workflow.Secrets); - Assert.Contains("NUGET_API_KEY", workflow.Secrets); + Assert.That(workflow.Secrets, Is.Not.Null); + Assert.That(workflow.Secrets, Has.Count.EqualTo(1)); + Assert.That(workflow.Secrets, Does.Contain("NUGET_API_KEY")); } - [Fact] + [Test] public async Task GetAllWorkflowsAsync_ReturnsAllWorkflows() { var projectRoot = Path.GetDirectoryName(Path.GetDirectoryName(_testWorkflowDir))!; var workflows = await _service.GetAllWorkflowsAsync(projectRoot); - Assert.Equal(2, workflows.Count); - Assert.Contains(workflows, w => w.Name == "Build"); - Assert.Contains(workflows, w => w.Name == "Deploy"); + Assert.That(workflows.Count, Is.EqualTo(2)); + Assert.That(workflows, Has.Some.Matches(w => w.Name == "Build")); + Assert.That(workflows, Has.Some.Matches(w => w.Name == "Deploy")); } - [Fact] + [Test] public void Constructor_CreatesServiceSuccessfully() { var service = new WorkflowAnalyzerService(); - Assert.NotNull(service); + Assert.That(service, Is.Not.Null); } }