Files
ChatBot/ChatBot.Tests/Telegram/Commands/TelegramCommandProcessorTests.cs
Leonid Pershin 2a26e84100
All checks were successful
SonarQube / Build and analyze (push) Successful in 3m39s
add tests
2025-10-21 02:30:04 +03:00

836 lines
22 KiB
C#

using ChatBot.Services;
using ChatBot.Services.Telegram.Commands;
using ChatBot.Services.Telegram.Interfaces;
using ChatBot.Services.Telegram.Services;
using ChatBot.Tests.TestUtilities;
using FluentAssertions;
using Microsoft.Extensions.Logging;
using Moq;
using Telegram.Bot;
using Telegram.Bot.Types;
namespace ChatBot.Tests.Telegram.Commands;
public class TelegramCommandProcessorTests : UnitTestBase
{
private readonly CommandRegistry _commandRegistry;
private readonly ChatService _chatService;
private readonly Mock<ILogger<TelegramCommandProcessor>> _loggerMock;
private readonly BotInfoService _botInfoService;
private readonly TelegramCommandProcessor _processor;
public TelegramCommandProcessorTests()
{
_commandRegistry = new CommandRegistry(
TestDataBuilder.Mocks.CreateLoggerMock<CommandRegistry>().Object,
Enumerable.Empty<ITelegramCommand>()
);
_chatService = new ChatService(
TestDataBuilder.Mocks.CreateLoggerMock<ChatService>().Object,
TestDataBuilder.Mocks.CreateAIServiceMock().Object,
TestDataBuilder.Mocks.CreateSessionStorageMock().Object,
TestDataBuilder
.Mocks.CreateOptionsMock(TestDataBuilder.Configurations.CreateAISettings())
.Object,
TestDataBuilder.Mocks.CreateCompressionServiceMock().Object
);
_loggerMock = TestDataBuilder.Mocks.CreateLoggerMock<TelegramCommandProcessor>();
_botInfoService = new BotInfoService(
TestDataBuilder.Mocks.CreateTelegramBotClient().Object,
TestDataBuilder.Mocks.CreateLoggerMock<BotInfoService>().Object
);
_processor = new TelegramCommandProcessor(
_commandRegistry,
_chatService,
_loggerMock.Object,
_botInfoService
);
}
[Fact]
public void Constructor_ShouldInitializeServices()
{
// Arrange & Act
var processor = new TelegramCommandProcessor(
_commandRegistry,
_chatService,
_loggerMock.Object,
_botInfoService
);
// Assert
processor.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldProcessAsRegularMessage_WhenNoCommandFound()
{
// Arrange
var messageText = "Hello bot";
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
result.Should().NotBeEmpty();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleEmptyMessage()
{
// Arrange
var messageText = "";
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleVeryLongMessage()
{
// Arrange
var messageText = new string('A', 10000);
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleEmptyUsername()
{
// Arrange
var messageText = "Hello";
var chatId = 12345L;
var username = "";
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleEmptyChatType()
{
// Arrange
var messageText = "Hello";
var chatId = 12345L;
var username = "testuser";
var chatType = "";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleEmptyChatTitle()
{
// Arrange
var messageText = "Hello";
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleNegativeChatId()
{
// Arrange
var messageText = "Hello";
var chatId = -12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleZeroChatId()
{
// Arrange
var messageText = "Hello";
var chatId = 0L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleVeryLongUsername()
{
// Arrange
var messageText = "Hello";
var chatId = 12345L;
var username = new string('A', 1000);
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleSpecialCharactersInMessage()
{
// Arrange
var messageText = "Hello! @#$%^&*()_+-=[]{}|;':\",./<>?";
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleUnicodeCharacters()
{
// Arrange
var messageText = "Привет! 🌍 Hello!";
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleNullMessage()
{
// Arrange
string messageText = null!;
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleNullUsername()
{
// Arrange
var messageText = "Hello";
var chatId = 12345L;
string username = null!;
var chatType = "private";
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleNullChatType()
{
// Arrange
var messageText = "Hello";
var chatId = 12345L;
var username = "testuser";
string chatType = null!;
var chatTitle = "Test Chat";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleNullChatTitle()
{
// Arrange
var messageText = "Hello";
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
string chatTitle = null!;
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleCancellationToken()
{
// Arrange
var messageText = "Hello bot";
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
using var cts = new CancellationTokenSource();
await cts.CancelAsync();
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle,
cancellationToken: cts.Token
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleReplyInfo()
{
// Arrange
var messageText = "Hello bot";
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
var replyInfo = new ReplyInfo
{
MessageId = 1,
UserId = 123,
Username = "testuser",
};
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle,
replyInfo
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_ShouldHandleNullReplyInfo()
{
// Arrange
var messageText = "Hello bot";
var chatId = 12345L;
var username = "testuser";
var chatType = "private";
var chatTitle = "Test Chat";
ReplyInfo? replyInfo = null;
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle,
replyInfo
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_WithReplyToBot_ShouldProcessMessage()
{
// Arrange
var botUser = new User
{
Id = 999,
Username = "testbot",
IsBot = true,
};
var botInfoServiceMock = new Mock<BotInfoService>(
TestDataBuilder.Mocks.CreateTelegramBotClient().Object,
TestDataBuilder.Mocks.CreateLoggerMock<BotInfoService>().Object
);
botInfoServiceMock.Setup(x => x.GetBotInfoAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(botUser);
var processor = new TelegramCommandProcessor(
_commandRegistry,
_chatService,
_loggerMock.Object,
botInfoServiceMock.Object
);
var replyInfo = new ReplyInfo
{
MessageId = 1,
UserId = 999,
Username = "testbot",
};
// Act
var result = await processor.ProcessMessageAsync(
"Test reply",
12345L,
"user",
"private",
"Test Chat",
replyInfo
);
// Assert
result.Should().NotBeNullOrEmpty();
}
[Fact]
public async Task ProcessMessageAsync_WithReplyToOtherUser_ShouldReturnEmpty()
{
// Arrange
var botUser = new User
{
Id = 999,
Username = "testbot",
IsBot = true,
};
var botInfoServiceMock = new Mock<BotInfoService>(
TestDataBuilder.Mocks.CreateTelegramBotClient().Object,
TestDataBuilder.Mocks.CreateLoggerMock<BotInfoService>().Object
);
botInfoServiceMock.Setup(x => x.GetBotInfoAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(botUser);
var processor = new TelegramCommandProcessor(
_commandRegistry,
_chatService,
_loggerMock.Object,
botInfoServiceMock.Object
);
var replyInfo = new ReplyInfo
{
MessageId = 1,
UserId = 123,
Username = "otheruser",
};
// Act
var result = await processor.ProcessMessageAsync(
"Test reply",
12345L,
"user",
"private",
"Test Chat",
replyInfo
);
// Assert
result.Should().BeEmpty();
}
[Fact]
public async Task ProcessMessageAsync_WithBotMention_ShouldProcessMessage()
{
// Arrange
var botUser = new User
{
Id = 999,
Username = "testbot",
IsBot = true,
};
var botInfoServiceMock = new Mock<BotInfoService>(
TestDataBuilder.Mocks.CreateTelegramBotClient().Object,
TestDataBuilder.Mocks.CreateLoggerMock<BotInfoService>().Object
);
botInfoServiceMock.Setup(x => x.GetBotInfoAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(botUser);
var processor = new TelegramCommandProcessor(
_commandRegistry,
_chatService,
_loggerMock.Object,
botInfoServiceMock.Object
);
// Act
var result = await processor.ProcessMessageAsync(
"Hello @testbot",
12345L,
"user",
"private",
"Test Chat"
);
// Assert
result.Should().NotBeNullOrEmpty();
}
[Fact]
public async Task ProcessMessageAsync_WithOtherUserMention_ShouldReturnEmpty()
{
// Arrange
var botUser = new User
{
Id = 999,
Username = "testbot",
IsBot = true,
};
var botInfoServiceMock = new Mock<BotInfoService>(
TestDataBuilder.Mocks.CreateTelegramBotClient().Object,
TestDataBuilder.Mocks.CreateLoggerMock<BotInfoService>().Object
);
botInfoServiceMock.Setup(x => x.GetBotInfoAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(botUser);
var processor = new TelegramCommandProcessor(
_commandRegistry,
_chatService,
_loggerMock.Object,
botInfoServiceMock.Object
);
// Act
var result = await processor.ProcessMessageAsync(
"Hello @otheruser",
12345L,
"user",
"private",
"Test Chat"
);
// Assert
result.Should().BeEmpty();
}
[Fact]
public async Task ProcessMessageAsync_WithCommand_ShouldExecuteCommand()
{
// Arrange
var commandMock = new Mock<ITelegramCommand>();
commandMock.Setup(x => x.CommandName).Returns("/test");
commandMock
.Setup(x => x.CanHandle(It.IsAny<string>()))
.Returns((string msg) => msg.StartsWith("/test"));
commandMock
.Setup(x =>
x.ExecuteAsync(It.IsAny<TelegramCommandContext>(), It.IsAny<CancellationToken>())
)
.ReturnsAsync("Command executed");
var commandRegistry = new CommandRegistry(
TestDataBuilder.Mocks.CreateLoggerMock<CommandRegistry>().Object,
new[] { commandMock.Object }
);
var processor = new TelegramCommandProcessor(
commandRegistry,
_chatService,
_loggerMock.Object,
_botInfoService
);
// Act
var result = await processor.ProcessMessageAsync(
"/test argument",
12345L,
"user",
"private",
"Test Chat"
);
// Assert
result.Should().Be("Command executed");
commandMock.Verify(
x => x.ExecuteAsync(It.IsAny<TelegramCommandContext>(), It.IsAny<CancellationToken>()),
Times.Once
);
}
[Fact]
public async Task ProcessMessageAsync_WithException_ShouldReturnErrorMessage()
{
// Arrange
var chatServiceMock = new Mock<ChatService>(
TestDataBuilder.Mocks.CreateLoggerMock<ChatService>().Object,
TestDataBuilder.Mocks.CreateAIServiceMock().Object,
TestDataBuilder.Mocks.CreateSessionStorageMock().Object,
TestDataBuilder
.Mocks.CreateOptionsMock(TestDataBuilder.Configurations.CreateAISettings())
.Object,
TestDataBuilder.Mocks.CreateCompressionServiceMock().Object
);
chatServiceMock
.Setup(x =>
x.ProcessMessageAsync(
It.IsAny<long>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<CancellationToken>()
)
)
.ThrowsAsync(new Exception("Test error"));
var processor = new TelegramCommandProcessor(
_commandRegistry,
chatServiceMock.Object,
_loggerMock.Object,
_botInfoService
);
// Act
var result = await processor.ProcessMessageAsync(
"Test message",
12345L,
"user",
"private",
"Test Chat"
);
// Assert
result.Should().Contain("Произошла ошибка");
}
[Fact]
public async Task ProcessMessageAsync_WithGroupChat_ShouldProcessCorrectly()
{
// Arrange
var messageText = "Hello";
var chatId = -100123456789L; // Group chat ID
var username = "testuser";
var chatType = "group";
var chatTitle = "Test Group";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_WithSupergroupChat_ShouldProcessCorrectly()
{
// Arrange
var messageText = "Hello";
var chatId = -100123456789L;
var username = "testuser";
var chatType = "supergroup";
var chatTitle = "Test Supergroup";
// Act
var result = await _processor.ProcessMessageAsync(
messageText,
chatId,
username,
chatType,
chatTitle
);
// Assert
result.Should().NotBeNull();
}
[Fact]
public async Task ProcessMessageAsync_WithMultipleMentions_IncludingBot_ShouldProcessMessage()
{
// Arrange
var botUser = new User
{
Id = 999,
Username = "testbot",
IsBot = true,
};
var botInfoServiceMock = new Mock<BotInfoService>(
TestDataBuilder.Mocks.CreateTelegramBotClient().Object,
TestDataBuilder.Mocks.CreateLoggerMock<BotInfoService>().Object
);
botInfoServiceMock.Setup(x => x.GetBotInfoAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(botUser);
var processor = new TelegramCommandProcessor(
_commandRegistry,
_chatService,
_loggerMock.Object,
botInfoServiceMock.Object
);
// Act
var result = await processor.ProcessMessageAsync(
"Hello @testbot and @otheruser",
12345L,
"user",
"group",
"Test Group"
);
// Assert
result.Should().NotBeNullOrEmpty();
}
}