Add more tests
This commit is contained in:
318
ChatBot.Tests/Services/Telegram/TelegramErrorHandlerTests.cs
Normal file
318
ChatBot.Tests/Services/Telegram/TelegramErrorHandlerTests.cs
Normal file
@@ -0,0 +1,318 @@
|
||||
using ChatBot.Services.Telegram.Services;
|
||||
using ChatBot.Tests.TestUtilities;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Exceptions;
|
||||
|
||||
namespace ChatBot.Tests.Services.Telegram;
|
||||
|
||||
public class TelegramErrorHandlerTests : UnitTestBase
|
||||
{
|
||||
private readonly Mock<ILogger<TelegramErrorHandler>> _loggerMock;
|
||||
private readonly Mock<ITelegramBotClient> _botClientMock;
|
||||
private readonly TelegramErrorHandler _errorHandler;
|
||||
|
||||
public TelegramErrorHandlerTests()
|
||||
{
|
||||
_loggerMock = new Mock<ILogger<TelegramErrorHandler>>();
|
||||
_botClientMock = new Mock<ITelegramBotClient>();
|
||||
_errorHandler = new TelegramErrorHandler(_loggerMock.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_ShouldCreateInstance()
|
||||
{
|
||||
// Act & Assert
|
||||
Assert.NotNull(_errorHandler);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandlePollingErrorAsync_WithApiRequestException_ShouldLogErrorWithFormattedMessage()
|
||||
{
|
||||
// Arrange
|
||||
var errorCode = 400;
|
||||
var errorMessage = "Bad Request: chat not found";
|
||||
var apiException = new ApiRequestException(errorMessage, errorCode);
|
||||
var cancellationToken = CancellationToken.None;
|
||||
|
||||
// Act
|
||||
await _errorHandler.HandlePollingErrorAsync(
|
||||
_botClientMock.Object,
|
||||
apiException,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
// Assert
|
||||
_loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Error,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) =>
|
||||
v.ToString()!
|
||||
.Contains($"Telegram API Error:\n[{errorCode}]\n{errorMessage}")
|
||||
),
|
||||
apiException,
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(400, "Bad Request")]
|
||||
[InlineData(401, "Unauthorized")]
|
||||
[InlineData(403, "Forbidden")]
|
||||
[InlineData(404, "Not Found")]
|
||||
[InlineData(429, "Too Many Requests")]
|
||||
[InlineData(500, "Internal Server Error")]
|
||||
public async Task HandlePollingErrorAsync_WithDifferentApiErrorCodes_ShouldLogCorrectFormat(
|
||||
int errorCode,
|
||||
string errorMessage
|
||||
)
|
||||
{
|
||||
// Arrange
|
||||
var apiException = new ApiRequestException(errorMessage, errorCode);
|
||||
var cancellationToken = CancellationToken.None;
|
||||
|
||||
// Act
|
||||
await _errorHandler.HandlePollingErrorAsync(
|
||||
_botClientMock.Object,
|
||||
apiException,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
// Assert
|
||||
_loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Error,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) =>
|
||||
v.ToString()!
|
||||
.Contains($"Telegram API Error:\n[{errorCode}]\n{errorMessage}")
|
||||
),
|
||||
apiException,
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandlePollingErrorAsync_WithGenericException_ShouldLogExceptionToString()
|
||||
{
|
||||
// Arrange
|
||||
var genericException = new InvalidOperationException("Something went wrong");
|
||||
var cancellationToken = CancellationToken.None;
|
||||
|
||||
// Act
|
||||
await _errorHandler.HandlePollingErrorAsync(
|
||||
_botClientMock.Object,
|
||||
genericException,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
// Assert
|
||||
_loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Error,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) =>
|
||||
v.ToString()!
|
||||
.Contains("System.InvalidOperationException: Something went wrong")
|
||||
),
|
||||
genericException,
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandlePollingErrorAsync_WithTimeoutException_ShouldLogTimeoutException()
|
||||
{
|
||||
// Arrange
|
||||
var timeoutException = new TimeoutException("Request timed out");
|
||||
var cancellationToken = CancellationToken.None;
|
||||
|
||||
// Act
|
||||
await _errorHandler.HandlePollingErrorAsync(
|
||||
_botClientMock.Object,
|
||||
timeoutException,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
// Assert
|
||||
_loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Error,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) =>
|
||||
v.ToString()!.Contains("System.TimeoutException: Request timed out")
|
||||
),
|
||||
timeoutException,
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandlePollingErrorAsync_WithHttpRequestException_ShouldLogHttpRequestException()
|
||||
{
|
||||
// Arrange
|
||||
var httpException = new HttpRequestException("Network error occurred");
|
||||
var cancellationToken = CancellationToken.None;
|
||||
|
||||
// Act
|
||||
await _errorHandler.HandlePollingErrorAsync(
|
||||
_botClientMock.Object,
|
||||
httpException,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
// Assert
|
||||
_loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Error,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) =>
|
||||
v.ToString()!
|
||||
.Contains(
|
||||
"System.Net.Http.HttpRequestException: Network error occurred"
|
||||
)
|
||||
),
|
||||
httpException,
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandlePollingErrorAsync_WithCancelledToken_ShouldCompleteSuccessfully()
|
||||
{
|
||||
// Arrange
|
||||
var exception = new InvalidOperationException("Test exception");
|
||||
using var cancellationTokenSource = new CancellationTokenSource();
|
||||
await cancellationTokenSource.CancelAsync();
|
||||
var cancelledToken = cancellationTokenSource.Token;
|
||||
|
||||
// Act
|
||||
await _errorHandler.HandlePollingErrorAsync(
|
||||
_botClientMock.Object,
|
||||
exception,
|
||||
cancelledToken
|
||||
);
|
||||
|
||||
// Assert
|
||||
_loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Error,
|
||||
It.IsAny<EventId>(),
|
||||
It.IsAny<It.IsAnyType>(),
|
||||
exception,
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandlePollingErrorAsync_ShouldReturnCompletedTask()
|
||||
{
|
||||
// Arrange
|
||||
var exception = new Exception("Test exception");
|
||||
var cancellationToken = CancellationToken.None;
|
||||
|
||||
// Act
|
||||
await _errorHandler.HandlePollingErrorAsync(
|
||||
_botClientMock.Object,
|
||||
exception,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
// Assert
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandlePollingErrorAsync_WithNestedException_ShouldLogOuterException()
|
||||
{
|
||||
// Arrange
|
||||
var innerException = new ArgumentException("Inner exception");
|
||||
var outerException = new InvalidOperationException("Outer exception", innerException);
|
||||
var cancellationToken = CancellationToken.None;
|
||||
|
||||
// Act
|
||||
await _errorHandler.HandlePollingErrorAsync(
|
||||
_botClientMock.Object,
|
||||
outerException,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
// Assert
|
||||
_loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Error,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) =>
|
||||
v.ToString()!
|
||||
.Contains("System.InvalidOperationException: Outer exception")
|
||||
),
|
||||
outerException,
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HandlePollingErrorAsync_WithAggregateException_ShouldLogAggregateException()
|
||||
{
|
||||
// Arrange
|
||||
var exceptions = new Exception[]
|
||||
{
|
||||
new InvalidOperationException("First exception"),
|
||||
new ArgumentException("Second exception"),
|
||||
};
|
||||
var aggregateException = new AggregateException("Multiple exceptions occurred", exceptions);
|
||||
var cancellationToken = CancellationToken.None;
|
||||
|
||||
// Act
|
||||
await _errorHandler.HandlePollingErrorAsync(
|
||||
_botClientMock.Object,
|
||||
aggregateException,
|
||||
cancellationToken
|
||||
);
|
||||
|
||||
// Assert
|
||||
_loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Error,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) =>
|
||||
v.ToString()!
|
||||
.Contains("System.AggregateException: Multiple exceptions occurred")
|
||||
),
|
||||
aggregateException,
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user