svrnty-mcp-gateway/tests/Svrnty.MCP.Gateway.Core.Tests/Interfaces/ICircuitBreakerTests.cs
Svrnty 19ef79362e refactor: rename OpenHarbor.MCP to Svrnty.MCP across all libraries
- Renamed all directories: OpenHarbor.MCP.* → Svrnty.MCP.*
- Updated all namespaces in 179 C# files
- Renamed 20 .csproj files and 3 .sln files
- Updated 193 documentation references
- Updated 33 references in main CODEX codebase
- Updated Codex.sln with new paths
- Build verified: 0 errors

Preparing for extraction to standalone repositories.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-22 21:04:17 -04:00

120 lines
3.7 KiB
C#

using Xunit;
using Moq;
using Svrnty.MCP.Gateway.Core.Interfaces;
namespace Svrnty.MCP.Gateway.Core.Tests.Interfaces;
/// <summary>
/// Unit tests for ICircuitBreaker interface following TDD approach.
/// Tests circuit breaker pattern implementation.
/// </summary>
public class ICircuitBreakerTests
{
[Fact]
public async Task ExecuteAsync_WithClosedCircuit_ExecutesOperation()
{
// Arrange
var mockCircuitBreaker = new Mock<ICircuitBreaker>();
var expectedResult = "success";
mockCircuitBreaker
.Setup(cb => cb.ExecuteAsync(
It.IsAny<Func<Task<string>>>(),
It.IsAny<CancellationToken>()))
.Returns<Func<Task<string>>, CancellationToken>((operation, ct) => operation());
// Act
var result = await mockCircuitBreaker.Object.ExecuteAsync(
async () => await Task.FromResult(expectedResult),
CancellationToken.None);
// Assert
Assert.Equal(expectedResult, result);
}
[Fact]
public async Task ExecuteAsync_WithOpenCircuit_ThrowsException()
{
// Arrange
var mockCircuitBreaker = new Mock<ICircuitBreaker>();
mockCircuitBreaker
.Setup(cb => cb.ExecuteAsync(
It.IsAny<Func<Task<string>>>(),
It.IsAny<CancellationToken>()))
.ThrowsAsync(new InvalidOperationException("Circuit is open"));
// Act & Assert
await Assert.ThrowsAsync<InvalidOperationException>(() =>
mockCircuitBreaker.Object.ExecuteAsync(
async () => await Task.FromResult("result"),
CancellationToken.None));
}
[Fact]
public void GetState_ReturnsCircuitState()
{
// Arrange
var mockCircuitBreaker = new Mock<ICircuitBreaker>();
mockCircuitBreaker.Setup(cb => cb.GetState()).Returns("Closed");
// Act
var state = mockCircuitBreaker.Object.GetState();
// Assert
Assert.Equal("Closed", state);
mockCircuitBreaker.Verify(cb => cb.GetState(), Times.Once);
}
[Fact]
public void Reset_ResetsCircuitBreaker()
{
// Arrange
var mockCircuitBreaker = new Mock<ICircuitBreaker>();
mockCircuitBreaker.Setup(cb => cb.Reset()).Verifiable();
// Act
mockCircuitBreaker.Object.Reset();
// Assert
mockCircuitBreaker.Verify(cb => cb.Reset(), Times.Once);
}
[Fact]
public async Task ExecuteAsync_WithMultipleFailures_OpensCircuit()
{
// Arrange
var mockCircuitBreaker = new Mock<ICircuitBreaker>();
var callCount = 0;
mockCircuitBreaker
.Setup(cb => cb.ExecuteAsync(
It.IsAny<Func<Task<string>>>(),
It.IsAny<CancellationToken>()))
.Returns<Func<Task<string>>, CancellationToken>((operation, ct) =>
{
callCount++;
if (callCount >= 3)
{
throw new InvalidOperationException("Circuit is open");
}
return operation();
});
// Act & Assert
// First two calls should succeed
await mockCircuitBreaker.Object.ExecuteAsync(
async () => await Task.FromResult("result1"),
CancellationToken.None);
await mockCircuitBreaker.Object.ExecuteAsync(
async () => await Task.FromResult("result2"),
CancellationToken.None);
// Third call should fail with open circuit
await Assert.ThrowsAsync<InvalidOperationException>(() =>
mockCircuitBreaker.Object.ExecuteAsync(
async () => await Task.FromResult("result3"),
CancellationToken.None));
}
}