feat(dal,templateMatcher): UnitFilterService переписан, теперь при подсчете количества связей для групп работ зонтик учитываются relationshipFilter. В TemplateMatcher добавлено изменение имени Unused шаблонов в конце имени добавляется DateTimeOffset.UtcNow.ToUnixTimeSeconds() для уникальности неиспользуемых шаблонов. Актуализированы unit-тесты

This commit is contained in:
Mikhail Kuznetsov
2025-12-15 11:50:12 +10:00
parent 03683a13d3
commit 8da4f226a7
9 changed files with 429 additions and 223 deletions

View File

@@ -0,0 +1,52 @@
using Microsoft.Extensions.Logging;
using MockQueryable;
using Moq;
using PARR.DAL.Contracts;
using PARR.DAL.DomainServices.Implementations;
using PARR.DAL.DomainServices.Interfaces;
using PARR.DAL.Models.Job;
using PARR.DAL.Models.Unit;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Unit;
namespace PARR.DAL.Tests.DomainServices.Implementations
{
public class ShortcodesServiceTests
{
private readonly Mock<ILogger<ShortcodesService>> loggerMock = new();
private readonly Mock<SettingsFromDb> settingsMock = new();
private readonly Mock<IJobService> jobServiceMock = new();
private readonly Mock<IUnitService> unitServiceMock = new();
private readonly Mock<IUnitInValueService> unitInValueServiceMock = new();
private readonly Mock<IUnitFieldService> unitFieldServiceMock = new();
private readonly Mock<IUnitFilterService> unitFilterServiceMock = new();
private ShortcodesService CreateService()
=> new(loggerMock.Object, settingsMock.Object, jobServiceMock.Object,
unitServiceMock.Object, unitFilterServiceMock.Object,
unitInValueServiceMock.Object, unitFieldServiceMock.Object);
[Fact]
public async Task ApplyShortcodesAsync_WithEc_ShouldReplaceEc()
{
// Arrange
var unitId = Guid.NewGuid();
var jobId = Guid.NewGuid();
var unit = new Unit { Id = unitId, Name = "Сервер_01" };
var job = new Job { Id = jobId, Name = "SAN ТО-1 Проверка работы фабрики SAN", TemplateNameMask = "%ЭК%", WorkGroupMask = "", WorkName = "Аудит" };
// ✅ БЕЗ .Object — ключевое!
unitServiceMock.Setup(x => x.Get()).Returns(new[] { unit }.BuildMock());
jobServiceMock.Setup(x => x.Get()).Returns(new[] { job }.BuildMock());
var service = CreateService();
// Act
var result = await service.ApplyShortcodesAsync("%ЭК%", unitId, jobId);
// Assert
Assert.Equal("Сервер_01", result);
}
}
}

View File

@@ -4,9 +4,8 @@ using Microsoft.Extensions.Logging;
using Moq;
using PARR.DAL.Context;
using PARR.DAL.DomainServices.Implementations;
using PARR.DAL.Services.Interfaces.Job;
using PARR.DAL.Services.Interfaces.Unit;
using Xunit;
using PARR.DAL.Services.Implementations.Job;
using PARR.DAL.Services.Implementations.Unit;
namespace PARR.DAL.Tests
{
@@ -27,16 +26,26 @@ namespace PARR.DAL.Tests
_context.Database.EnsureCreated();
TestDataGenerator.Seed(_context);
// Логгеры
var logger = Mock.Of<ILogger<UnitFilterService>>();
var jobServiceLogger = Mock.Of<ILogger<JobService>>();
var unitServiceLogger = Mock.Of<ILogger<UnitService>>();
var unitInUnitServiceLogger = Mock.Of<ILogger<UnitInUnitService>>();
var unitInValueServiceLogger = Mock.Of<ILogger<UnitInValueService>>();
// Используем реальные сервисы, работающие с _context
var jobServiceMock = new Mock<IJobService>();
jobServiceMock.Setup(x => x.Get()).Returns(() => _context.Jobs);
// Реальные сервисы с правильными конструкторами
var jobService = new JobService(_context, jobServiceLogger);
var unitService = new UnitService(_context, unitServiceLogger);
var unitInUnitService = new UnitInUnitService(_context, unitInUnitServiceLogger);
var unitInValueService = new UnitInValueService(unitInValueServiceLogger, _context); // ← logger first!
var unitServiceMock = new Mock<IUnitService>();
unitServiceMock.Setup(x => x.Get()).Returns(() => _context.Units);
_service = new UnitFilterService(logger, jobServiceMock.Object, unitServiceMock.Object);
_service = new UnitFilterService(
logger,
jobService,
unitService,
unitInUnitService,
unitInValueService
);
}
public void Dispose() => _context.Dispose();
@@ -75,46 +84,5 @@ namespace PARR.DAL.Tests
// Assert
result.Should().Contain(new[] { "СХД-КМТ-CISCO-MDS9148-1-ДВС", "СХД-КМТ-CISCO-MDS9148-3-ДВС" });
}
//[Fact]
//public async Task GetRelatedUnitNamesAsync_WithChildRelationshipFilter_ShouldReturnExpectedNames()
//{
// // Arrange
// var jobId = _context.Jobs.First(j => j.Name == "TestJob_2").Id;
// var unitId = TestDataGenerator.UnitWId;
// // Проверим связи вручную
// var childLinks = await _context.UnitInUnits
// .Where(u => u.ParentUnitId == unitId)
// .ToListAsync();
// var childIds = childLinks.Select(l => l.ChildUnitId).ToList();
// var childUnits = await _context.Units
// .Where(u => childIds.Contains(u.Id))
// .ToListAsync();
// Console.WriteLine($"Child units of {unitId}:");
// foreach (var u in childUnits)
// {
// Console.WriteLine($" - {u.Id} ({u.Name})");
// var values = await _context.UnitInValues
// .Where(v => v.UnitId == u.Id && v.FieldId == TestDataGenerator.FieldId1)
// .ToListAsync();
// foreach (var v in values)
// {
// var val = await _context.UnitFieldValues.FindAsync(v.ValueId);
// Console.WriteLine($" FieldId1 = {val?.Value}");
// }
// }
// // Act
// var result = await _service.GetRelatedUnitNamesAsync(jobId, unitId);
// Console.WriteLine($"Result: [{string.Join(", ", result)}]");
// // Assert
// result.Should().Contain(new[] { "СХД-КМТ-CISCO-MDS9148-1-ДВС", "СХД-КМТ-CISCO-MDS9148-3-ДВС" });
//}
}
}

View File

@@ -12,6 +12,7 @@
<PackageReference Include="FluentAssertions" Version="8.8.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="7.0.20" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="MockQueryable.Moq" Version="7.0.3" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">