Files
jdescopingtool/NEW/tests/JdeScoping.DataSync.Tests/Services/SearchRepositoryTests.cs
T
Joseph Doherty 91b516e197 feat: implement WorkProcessor and search execution services
- SearchRepository: Search table operations with Dapper
- SearchExecutionService: Search pipeline with proper cancellation handling
- WorkProcessor: Unified BackgroundService for syncs and searches
- SearchNotificationService: SignalR notifications in Api layer

All 45 new tests pass. Proper shutdown vs timeout distinction
prevents marking searches as error on host shutdown.
2026-01-07 06:18:35 -05:00

130 lines
4.0 KiB
C#

using JdeScoping.DataAccess.Interfaces;
using JdeScoping.DataSync.Services;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using NSubstitute;
using Shouldly;
namespace JdeScoping.DataSync.Tests.Services;
/// <summary>
/// Unit tests for SearchRepository.
/// Tests constructor validation and interface contract compliance.
/// Integration tests with actual database are required for full coverage.
/// </summary>
public class SearchRepositoryTests
{
private readonly IDbConnectionFactory _connectionFactory;
private readonly ILogger<SearchRepository> _logger;
public SearchRepositoryTests()
{
_connectionFactory = Substitute.For<IDbConnectionFactory>();
_logger = NullLogger<SearchRepository>.Instance;
}
#region Constructor Tests
[Fact]
public void Constructor_WithNullConnectionFactory_ThrowsArgumentNullException()
{
// Act & Assert
var exception = Should.Throw<ArgumentNullException>(() =>
new SearchRepository(null!, _logger));
exception.ParamName.ShouldBe("connectionFactory");
}
[Fact]
public void Constructor_WithNullLogger_ThrowsArgumentNullException()
{
// Act & Assert
var exception = Should.Throw<ArgumentNullException>(() =>
new SearchRepository(_connectionFactory, null!));
exception.ParamName.ShouldBe("logger");
}
[Fact]
public void Constructor_WithValidDependencies_CreatesInstance()
{
// Act
var repository = new SearchRepository(_connectionFactory, _logger);
// Assert
repository.ShouldNotBeNull();
}
#endregion
#region Interface Contract Tests
[Fact]
public void SearchRepository_ImplementsISearchRepository()
{
// Arrange & Act
var repository = new SearchRepository(_connectionFactory, _logger);
// Assert
repository.ShouldBeAssignableTo<JdeScoping.DataSync.Contracts.ISearchRepository>();
}
[Fact]
public void GetNextQueuedSearchAsync_HasCorrectSignature()
{
// Arrange
var repository = new SearchRepository(_connectionFactory, _logger);
// Act - Verify method exists with correct return type
var methodInfo = typeof(SearchRepository).GetMethod(nameof(SearchRepository.GetNextQueuedSearchAsync));
// Assert
methodInfo.ShouldNotBeNull();
methodInfo.ReturnType.ShouldBe(typeof(Task<JdeScoping.Core.Models.Search.Search?>));
}
[Fact]
public void ResetPartialSearchesAsync_HasCorrectSignature()
{
// Arrange
var repository = new SearchRepository(_connectionFactory, _logger);
// Act - Verify method exists with correct return type
var methodInfo = typeof(SearchRepository).GetMethod(nameof(SearchRepository.ResetPartialSearchesAsync));
// Assert
methodInfo.ShouldNotBeNull();
methodInfo.ReturnType.ShouldBe(typeof(Task<int>));
}
[Fact]
public void StartSearchAsync_HasCorrectSignature()
{
// Arrange
var repository = new SearchRepository(_connectionFactory, _logger);
// Act - Verify method exists with correct return type
var methodInfo = typeof(SearchRepository).GetMethod(nameof(SearchRepository.StartSearchAsync));
// Assert
methodInfo.ShouldNotBeNull();
methodInfo.ReturnType.ShouldBe(typeof(Task));
}
[Fact]
public void CompleteSearchAsync_HasCorrectSignature()
{
// Arrange
var repository = new SearchRepository(_connectionFactory, _logger);
// Act - Verify method exists with correct return type
var methodInfo = typeof(SearchRepository).GetMethod(nameof(SearchRepository.CompleteSearchAsync));
// Assert
methodInfo.ShouldNotBeNull();
methodInfo.ReturnType.ShouldBe(typeof(Task));
}
#endregion
}