using Cleanuparr.Infrastructure.Events.Interfaces; using Cleanuparr.Infrastructure.Features.Arr.Interfaces; using Cleanuparr.Infrastructure.Features.Context; using Cleanuparr.Infrastructure.Features.DownloadClient; using Cleanuparr.Infrastructure.Features.Files; using Cleanuparr.Infrastructure.Features.Jobs; using Cleanuparr.Infrastructure.Features.MalwareBlocker; using Cleanuparr.Persistence; using MassTransit; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Time.Testing; using Moq; namespace Cleanuparr.Infrastructure.Tests.Features.Jobs.TestHelpers; /// /// Base fixture for job handler tests providing common mock dependencies /// public class JobHandlerFixture : IDisposable { public DataContext DataContext { get; private set; } public MemoryCache Cache { get; } public Mock MessageBus { get; } public Mock ArrClientFactory { get; } public Mock ArrQueueIterator { get; } public Mock DownloadServiceFactory { get; } public Mock EventPublisher { get; } public Mock BlocklistProvider { get; } public Mock HardLinkFileService { get; } public FakeTimeProvider TimeProvider { get; private set; } public JobHandlerFixture() { DataContext = TestDataContextFactory.Create(); Cache = new MemoryCache(new MemoryCacheOptions()); MessageBus = new Mock(); ArrClientFactory = new Mock(); ArrQueueIterator = new Mock(); DownloadServiceFactory = new Mock(); EventPublisher = new Mock(); BlocklistProvider = new Mock(); HardLinkFileService = new Mock(); TimeProvider = new FakeTimeProvider(); // Setup default behaviors SetupDefaultBehaviors(); // Setup JobRunId in context for tests ContextProvider.SetJobRunId(Guid.NewGuid()); } private void SetupDefaultBehaviors() { // EventPublisher methods return completed task by default EventPublisher .Setup(x => x.PublishAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns(Task.CompletedTask); } /// /// Creates a mock logger for a specific handler type /// public Mock> CreateLogger() where T : GenericHandler { return new Mock>(); } /// /// Creates a mock download service /// public Mock CreateMockDownloadService(string clientName = "Test Client") { var mock = new Mock(); mock.Setup(x => x.ClientConfig).Returns(new Persistence.Models.Configuration.DownloadClientConfig { Id = Guid.NewGuid(), Name = clientName, Type = Domain.Enums.DownloadClientType.Torrent, TypeName = Domain.Enums.DownloadClientTypeName.qBittorrent, Enabled = true, Host = new Uri("http://localhost:8080") }); mock.Setup(x => x.LoginAsync()).Returns(Task.CompletedTask); return mock; } /// /// Sets up the DownloadServiceFactory to return the specified mock services /// public void SetupDownloadServices(params Mock[] services) { foreach (var service in services) { DownloadServiceFactory .Setup(x => x.GetDownloadService(service.Object.ClientConfig)) .Returns(service.Object); } } /// /// Creates a fresh DataContext, disposing the old one /// public DataContext RecreateDataContext(bool seedData = true) { DataContext?.Dispose(); DataContext = TestDataContextFactory.Create(seedData); return DataContext; } public void ResetMocks() { MessageBus.Reset(); ArrClientFactory.Reset(); ArrQueueIterator.Reset(); DownloadServiceFactory.Reset(); EventPublisher.Reset(); BlocklistProvider.Reset(); HardLinkFileService.Reset(); Cache.Clear(); TimeProvider = new FakeTimeProvider(); SetupDefaultBehaviors(); // Setup fresh JobRunId for each test ContextProvider.SetJobRunId(Guid.NewGuid()); } public void Dispose() { DataContext?.Dispose(); Cache?.Dispose(); GC.SuppressFinalize(this); } }