This commit is contained in:
@@ -255,4 +255,328 @@ public class DatabaseInitializationServiceTests : UnitTestBase
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartAsync_WhenDatabaseExists_ShouldLogAndMigrate()
|
||||
{
|
||||
// Arrange
|
||||
var dbPath = $"TestDb_{Guid.NewGuid()}.db";
|
||||
var services = new ServiceCollection();
|
||||
services.AddDbContext<ChatBotDbContext>(options =>
|
||||
options.UseSqlite($"Data Source={dbPath}")
|
||||
.ConfigureWarnings(w => w.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning))
|
||||
);
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
var loggerMock = new Mock<ILogger<DatabaseInitializationService>>();
|
||||
|
||||
var service = new DatabaseInitializationService(serviceProvider, loggerMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
// Act
|
||||
await service.StartAsync(CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Information,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) => v.ToString()!.Contains("Starting database initialization")
|
||||
),
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
|
||||
loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Information,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) =>
|
||||
v.ToString()!
|
||||
.Contains("Database initialization completed successfully")
|
||||
),
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup
|
||||
serviceProvider.Dispose();
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
if (File.Exists(dbPath))
|
||||
{
|
||||
try { File.Delete(dbPath); } catch { /* Ignore cleanup errors */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StopAsync_WithCancellationToken_ShouldComplete()
|
||||
{
|
||||
// Arrange
|
||||
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||
var loggerMock = new Mock<ILogger<DatabaseInitializationService>>();
|
||||
var service = new DatabaseInitializationService(
|
||||
serviceProviderMock.Object,
|
||||
loggerMock.Object
|
||||
);
|
||||
var cts = new CancellationTokenSource();
|
||||
|
||||
// Act
|
||||
await service.StopAsync(cts.Token);
|
||||
|
||||
// Assert
|
||||
loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Information,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) => v.ToString()!.Contains("Database initialization service stopped")
|
||||
),
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StopAsync_WhenCancellationRequested_ShouldStillComplete()
|
||||
{
|
||||
// Arrange
|
||||
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||
var loggerMock = new Mock<ILogger<DatabaseInitializationService>>();
|
||||
var service = new DatabaseInitializationService(
|
||||
serviceProviderMock.Object,
|
||||
loggerMock.Object
|
||||
);
|
||||
var cts = new CancellationTokenSource();
|
||||
cts.Cancel();
|
||||
|
||||
// Act
|
||||
await service.StopAsync(cts.Token);
|
||||
|
||||
// Assert
|
||||
loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Information,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) => v.ToString()!.Contains("Database initialization service stopped")
|
||||
),
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartAsync_ShouldHandleDatabaseDoesNotExistException()
|
||||
{
|
||||
// Arrange
|
||||
var dbPath = $"TestDb_{Guid.NewGuid()}.db";
|
||||
var services = new ServiceCollection();
|
||||
services.AddDbContext<ChatBotDbContext>(options =>
|
||||
options.UseSqlite($"Data Source={dbPath}")
|
||||
.ConfigureWarnings(w => w.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning))
|
||||
);
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
var loggerMock = new Mock<ILogger<DatabaseInitializationService>>();
|
||||
|
||||
var service = new DatabaseInitializationService(serviceProvider, loggerMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
// Act
|
||||
await service.StartAsync(CancellationToken.None);
|
||||
|
||||
// Assert - service should complete successfully
|
||||
loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Information,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) =>
|
||||
v.ToString()!
|
||||
.Contains("Database initialization completed successfully")
|
||||
),
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup
|
||||
serviceProvider.Dispose();
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
if (File.Exists(dbPath))
|
||||
{
|
||||
try { File.Delete(dbPath); } catch { /* Ignore cleanup errors */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartAsync_WithValidDatabase_ShouldLogDatabaseExists()
|
||||
{
|
||||
// Arrange
|
||||
var dbPath = $"TestDb_{Guid.NewGuid()}.db";
|
||||
var services = new ServiceCollection();
|
||||
services.AddDbContext<ChatBotDbContext>(options =>
|
||||
options.UseSqlite($"Data Source={dbPath}")
|
||||
.ConfigureWarnings(w => w.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning))
|
||||
);
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
var loggerMock = new Mock<ILogger<DatabaseInitializationService>>();
|
||||
|
||||
var service = new DatabaseInitializationService(serviceProvider, loggerMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
// Act
|
||||
await service.StartAsync(CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Information,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>((v, t) => true), // Any log message
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.AtLeastOnce
|
||||
);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup
|
||||
serviceProvider.Dispose();
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
if (File.Exists(dbPath))
|
||||
{
|
||||
try { File.Delete(dbPath); } catch { /* Ignore cleanup errors */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatabaseInitializationService_ShouldImplementIHostedService()
|
||||
{
|
||||
// Arrange
|
||||
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||
var loggerMock = new Mock<ILogger<DatabaseInitializationService>>();
|
||||
|
||||
// Act
|
||||
var service = new DatabaseInitializationService(
|
||||
serviceProviderMock.Object,
|
||||
loggerMock.Object
|
||||
);
|
||||
|
||||
// Assert
|
||||
service.Should().BeAssignableTo<Microsoft.Extensions.Hosting.IHostedService>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartAsync_MultipleCallsInSequence_ShouldWork()
|
||||
{
|
||||
// Arrange
|
||||
var dbPath = $"TestDb_{Guid.NewGuid()}.db";
|
||||
var services = new ServiceCollection();
|
||||
services.AddDbContext<ChatBotDbContext>(options =>
|
||||
options.UseSqlite($"Data Source={dbPath}")
|
||||
.ConfigureWarnings(w => w.Ignore(Microsoft.EntityFrameworkCore.Diagnostics.RelationalEventId.PendingModelChangesWarning))
|
||||
);
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
var loggerMock = new Mock<ILogger<DatabaseInitializationService>>();
|
||||
var service = new DatabaseInitializationService(serviceProvider, loggerMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
// Act
|
||||
await service.StartAsync(CancellationToken.None);
|
||||
await service.StopAsync(CancellationToken.None);
|
||||
|
||||
// Assert - should complete without exceptions
|
||||
loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Information,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) =>
|
||||
v.ToString()!
|
||||
.Contains("Database initialization completed successfully")
|
||||
),
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Cleanup
|
||||
serviceProvider.Dispose();
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
if (File.Exists(dbPath))
|
||||
{
|
||||
try { File.Delete(dbPath); } catch { /* Ignore cleanup errors */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StopAsync_WithoutStartAsync_ShouldComplete()
|
||||
{
|
||||
// Arrange
|
||||
var serviceProviderMock = new Mock<IServiceProvider>();
|
||||
var loggerMock = new Mock<ILogger<DatabaseInitializationService>>();
|
||||
var service = new DatabaseInitializationService(
|
||||
serviceProviderMock.Object,
|
||||
loggerMock.Object
|
||||
);
|
||||
|
||||
// Act
|
||||
await service.StopAsync(CancellationToken.None);
|
||||
|
||||
// Assert - should complete without exceptions
|
||||
loggerMock.Verify(
|
||||
x =>
|
||||
x.Log(
|
||||
LogLevel.Information,
|
||||
It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>(
|
||||
(v, t) => v.ToString()!.Contains("Database initialization service stopped")
|
||||
),
|
||||
It.IsAny<Exception>(),
|
||||
It.IsAny<Func<It.IsAnyType, Exception?, string>>()
|
||||
),
|
||||
Times.Once
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,4 +176,265 @@ public class DatabaseSessionStorageTests : TestBase
|
||||
result.Should().Be(expectedCount);
|
||||
_repositoryMock.Verify(x => x.CleanupOldSessionsAsync(24), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetOrCreate_ShouldThrowInvalidOperationException_WhenRepositoryThrows()
|
||||
{
|
||||
// Arrange
|
||||
_repositoryMock
|
||||
.Setup(x => x.GetOrCreateAsync(12345, "private", "Test Chat"))
|
||||
.ThrowsAsync(new Exception("Database error"));
|
||||
|
||||
// Act
|
||||
var act = () => _sessionStorage.GetOrCreate(12345, "private", "Test Chat");
|
||||
|
||||
// Assert
|
||||
act.Should()
|
||||
.Throw<InvalidOperationException>()
|
||||
.WithMessage("Failed to get or create session for chat 12345")
|
||||
.WithInnerException<Exception>()
|
||||
.WithMessage("Database error");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Get_ShouldReturnNull_WhenRepositoryThrows()
|
||||
{
|
||||
// Arrange
|
||||
_repositoryMock
|
||||
.Setup(x => x.GetByChatIdAsync(12345))
|
||||
.ThrowsAsync(new Exception("Database error"));
|
||||
|
||||
// Act
|
||||
var result = _sessionStorage.Get(12345);
|
||||
|
||||
// Assert
|
||||
result.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SaveSessionAsync_ShouldLogWarning_WhenSessionNotFound()
|
||||
{
|
||||
// Arrange
|
||||
var session = TestDataBuilder.ChatSessions.CreateBasicSession(12345, "private");
|
||||
_repositoryMock
|
||||
.Setup(x => x.GetByChatIdAsync(12345))
|
||||
.ReturnsAsync((ChatSessionEntity?)null);
|
||||
|
||||
// Act
|
||||
await _sessionStorage.SaveSessionAsync(session);
|
||||
|
||||
// Assert
|
||||
_repositoryMock.Verify(x => x.GetByChatIdAsync(12345), Times.Once);
|
||||
_repositoryMock.Verify(x => x.UpdateAsync(It.IsAny<ChatSessionEntity>()), Times.Never);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SaveSessionAsync_ShouldThrowInvalidOperationException_WhenRepositoryThrows()
|
||||
{
|
||||
// Arrange
|
||||
var session = TestDataBuilder.ChatSessions.CreateBasicSession(12345, "private");
|
||||
_repositoryMock
|
||||
.Setup(x => x.GetByChatIdAsync(12345))
|
||||
.ThrowsAsync(new Exception("Database error"));
|
||||
|
||||
// Act
|
||||
var act = async () => await _sessionStorage.SaveSessionAsync(session);
|
||||
|
||||
// Assert
|
||||
var exception = await act.Should()
|
||||
.ThrowAsync<InvalidOperationException>()
|
||||
.WithMessage("Failed to save session for chat 12345");
|
||||
exception
|
||||
.And.InnerException.Should()
|
||||
.BeOfType<Exception>()
|
||||
.Which.Message.Should()
|
||||
.Be("Database error");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SaveSessionAsync_ShouldClearMessagesAndAddNew()
|
||||
{
|
||||
// Arrange
|
||||
var session = TestDataBuilder.ChatSessions.CreateBasicSession(12345, "private");
|
||||
session.AddUserMessage("Test message", "user1");
|
||||
session.AddAssistantMessage("Test response");
|
||||
|
||||
var sessionEntity = TestDataBuilder.Mocks.CreateChatSessionEntity();
|
||||
_repositoryMock.Setup(x => x.GetByChatIdAsync(12345)).ReturnsAsync(sessionEntity);
|
||||
_repositoryMock
|
||||
.Setup(x => x.UpdateAsync(It.IsAny<ChatSessionEntity>()))
|
||||
.ReturnsAsync(sessionEntity);
|
||||
|
||||
// Act
|
||||
await _sessionStorage.SaveSessionAsync(session);
|
||||
|
||||
// Assert
|
||||
_repositoryMock.Verify(x => x.ClearMessagesAsync(It.IsAny<int>()), Times.Once);
|
||||
_repositoryMock.Verify(
|
||||
x =>
|
||||
x.AddMessageAsync(
|
||||
It.IsAny<int>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<int>()
|
||||
),
|
||||
Times.Exactly(2)
|
||||
);
|
||||
_repositoryMock.Verify(x => x.UpdateAsync(It.IsAny<ChatSessionEntity>()), Times.Once);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Remove_ShouldReturnFalse_WhenRepositoryThrows()
|
||||
{
|
||||
// Arrange
|
||||
_repositoryMock
|
||||
.Setup(x => x.DeleteAsync(12345))
|
||||
.ThrowsAsync(new Exception("Database error"));
|
||||
|
||||
// Act
|
||||
var result = _sessionStorage.Remove(12345);
|
||||
|
||||
// Assert
|
||||
result.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetActiveSessionsCount_ShouldReturnZero_WhenRepositoryThrows()
|
||||
{
|
||||
// Arrange
|
||||
_repositoryMock
|
||||
.Setup(x => x.GetActiveSessionsCountAsync())
|
||||
.ThrowsAsync(new Exception("Database error"));
|
||||
|
||||
// Act
|
||||
var result = _sessionStorage.GetActiveSessionsCount();
|
||||
|
||||
// Assert
|
||||
result.Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CleanupOldSessions_ShouldReturnZero_WhenRepositoryThrows()
|
||||
{
|
||||
// Arrange
|
||||
_repositoryMock
|
||||
.Setup(x => x.CleanupOldSessionsAsync(24))
|
||||
.ThrowsAsync(new Exception("Database error"));
|
||||
|
||||
// Act
|
||||
var result = _sessionStorage.CleanupOldSessions(24);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetOrCreate_WithCompressionService_ShouldSetCompressionService()
|
||||
{
|
||||
// Arrange
|
||||
var compressionServiceMock = TestDataBuilder.Mocks.CreateCompressionServiceMock();
|
||||
var storageWithCompression = new DatabaseSessionStorage(
|
||||
_repositoryMock.Object,
|
||||
Mock.Of<ILogger<DatabaseSessionStorage>>(),
|
||||
compressionServiceMock.Object
|
||||
);
|
||||
|
||||
var sessionEntity = TestDataBuilder.Mocks.CreateChatSessionEntity();
|
||||
_repositoryMock
|
||||
.Setup(x => x.GetOrCreateAsync(12345, "private", "Test Chat"))
|
||||
.ReturnsAsync(sessionEntity);
|
||||
|
||||
// Act
|
||||
var result = storageWithCompression.GetOrCreate(12345, "private", "Test Chat");
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
result.ChatId.Should().Be(12345);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Get_WithCompressionService_ShouldSetCompressionService()
|
||||
{
|
||||
// Arrange
|
||||
var loggerMock = new Mock<ILogger<DatabaseSessionStorage>>();
|
||||
var compressionServiceMock = TestDataBuilder.Mocks.CreateCompressionServiceMock();
|
||||
var storageWithCompression = new DatabaseSessionStorage(
|
||||
_repositoryMock.Object,
|
||||
loggerMock.Object,
|
||||
compressionServiceMock.Object
|
||||
);
|
||||
|
||||
var sessionEntity = TestDataBuilder.Mocks.CreateChatSessionEntity();
|
||||
sessionEntity.Messages.Add(
|
||||
new ChatMessageEntity
|
||||
{
|
||||
Id = 1,
|
||||
SessionId = sessionEntity.Id,
|
||||
Content = "Test",
|
||||
Role = "user",
|
||||
MessageOrder = 0,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
}
|
||||
);
|
||||
|
||||
_repositoryMock.Setup(x => x.GetByChatIdAsync(12345)).ReturnsAsync(sessionEntity);
|
||||
|
||||
// Act
|
||||
var result = storageWithCompression.Get(12345);
|
||||
|
||||
// Assert
|
||||
_repositoryMock.Verify(x => x.GetByChatIdAsync(12345), Times.Once);
|
||||
result.Should().NotBeNull();
|
||||
result!.GetMessageCount().Should().Be(1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SaveSessionAsync_WithMultipleMessages_ShouldSaveInCorrectOrder()
|
||||
{
|
||||
// Arrange
|
||||
var session = TestDataBuilder.ChatSessions.CreateBasicSession(12345, "private");
|
||||
session.AddUserMessage("Message 1", "user1");
|
||||
session.AddAssistantMessage("Response 1");
|
||||
session.AddUserMessage("Message 2", "user1");
|
||||
session.AddAssistantMessage("Response 2");
|
||||
|
||||
var sessionEntity = TestDataBuilder.Mocks.CreateChatSessionEntity();
|
||||
_repositoryMock.Setup(x => x.GetByChatIdAsync(12345)).ReturnsAsync(sessionEntity);
|
||||
_repositoryMock
|
||||
.Setup(x => x.UpdateAsync(It.IsAny<ChatSessionEntity>()))
|
||||
.ReturnsAsync(sessionEntity);
|
||||
|
||||
// Act
|
||||
await _sessionStorage.SaveSessionAsync(session);
|
||||
|
||||
// Assert
|
||||
_repositoryMock.Verify(x => x.ClearMessagesAsync(It.IsAny<int>()), Times.Once);
|
||||
_repositoryMock.Verify(
|
||||
x =>
|
||||
x.AddMessageAsync(
|
||||
It.IsAny<int>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<int>()
|
||||
),
|
||||
Times.Exactly(4)
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetOrCreate_WithDefaultParameters_ShouldUseDefaults()
|
||||
{
|
||||
// Arrange
|
||||
var sessionEntity = TestDataBuilder.Mocks.CreateChatSessionEntity();
|
||||
_repositoryMock
|
||||
.Setup(x => x.GetOrCreateAsync(12345, "private", ""))
|
||||
.ReturnsAsync(sessionEntity);
|
||||
|
||||
// Act
|
||||
var result = _sessionStorage.GetOrCreate(12345);
|
||||
|
||||
// Assert
|
||||
result.Should().NotBeNull();
|
||||
_repositoryMock.Verify(x => x.GetOrCreateAsync(12345, "private", ""), Times.Once);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using ChatBot.Services.Telegram.Services;
|
||||
using ChatBot.Tests.TestUtilities;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using Telegram.Bot;
|
||||
using Telegram.Bot.Types;
|
||||
using Xunit;
|
||||
|
||||
namespace ChatBot.Tests.Services.Telegram;
|
||||
|
||||
public class TelegramMessageSenderWrapperTests : UnitTestBase
|
||||
{
|
||||
private readonly Mock<ITelegramBotClient> _botClientMock;
|
||||
private readonly TelegramMessageSenderWrapper _wrapper;
|
||||
|
||||
public TelegramMessageSenderWrapperTests()
|
||||
{
|
||||
_botClientMock = TestDataBuilder.Mocks.CreateTelegramBotClient();
|
||||
_wrapper = new TelegramMessageSenderWrapper(_botClientMock.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Constructor_ShouldInitializeCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var botClient = TestDataBuilder.Mocks.CreateTelegramBotClient().Object;
|
||||
|
||||
// Act
|
||||
var wrapper = new TelegramMessageSenderWrapper(botClient);
|
||||
|
||||
// Assert
|
||||
wrapper.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SendMessageAsync_ShouldBePublicMethod()
|
||||
{
|
||||
// Arrange & Act
|
||||
var method = typeof(TelegramMessageSenderWrapper).GetMethod("SendMessageAsync");
|
||||
|
||||
// Assert
|
||||
method.Should().NotBeNull();
|
||||
method!.IsPublic.Should().BeTrue();
|
||||
method.ReturnType.Should().Be<Task<Message>>();
|
||||
}
|
||||
}
|
||||
@@ -329,4 +329,8 @@ public class TelegramBotClientWrapperTests : UnitTestBase
|
||||
var attributes = returnType.GetCustomAttributes(false);
|
||||
attributes.Should().NotBeNull();
|
||||
}
|
||||
|
||||
// Note: Tests for GetMeAsync removed because GetMe is an extension method
|
||||
// and cannot be mocked with Moq. The wrapper simply delegates to the
|
||||
// TelegramBotClient extension method, which is tested by the Telegram.Bot library itself.
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user