From 6db0554b1ea436db869f27aed140b310b9c5023e Mon Sep 17 00:00:00 2001 From: yv01p Date: Sat, 20 Dec 2025 19:40:00 +0000 Subject: [PATCH] test: add ContentServiceBaseTests skeleton for Phase 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds unit test file for ContentServiceBase with documented test cases. Tests are commented out until ContentServiceBase is created in Phase 1: - 2 audit helper method tests - 2 scope provider access pattern tests - 2 logger injection tests - 1 repository access test 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../Services/ContentServiceBaseTests.cs | 231 ++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Services/ContentServiceBaseTests.cs diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Services/ContentServiceBaseTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Services/ContentServiceBaseTests.cs new file mode 100644 index 0000000000..4921850d92 --- /dev/null +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Services/ContentServiceBaseTests.cs @@ -0,0 +1,231 @@ +// Copyright (c) Umbraco. +// See LICENSE for more details. + +using Microsoft.Extensions.Logging; +using Moq; +using NUnit.Framework; +using Umbraco.Cms.Core.Events; +using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Persistence.Repositories; +using Umbraco.Cms.Core.Scoping; +using Umbraco.Cms.Core.Services; + +namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Services; + +/// +/// Unit tests for ContentServiceBase (shared infrastructure for extracted services). +/// These tests establish the expected contract for the base class before it's created. +/// +/// +/// ContentServiceBase will be created in Phase 1. These tests validate the design requirements: +/// - Audit helper method behavior +/// - Scope provider access patterns +/// - Logger injection patterns +/// +[TestFixture] +public class ContentServiceBaseTests +{ + // Note: These tests will be uncommented when ContentServiceBase is created in Phase 1. + // For now, they serve as documentation of the expected behavior. + + /* + private Mock _scopeProviderMock; + private Mock _auditServiceMock; + private Mock _eventMessagesFactoryMock; + private Mock> _loggerMock; + private TestContentService _service; + + [SetUp] + public void Setup() + { + _scopeProviderMock = new Mock(); + _auditServiceMock = new Mock(); + _eventMessagesFactoryMock = new Mock(); + _loggerMock = new Mock>(); + + _eventMessagesFactoryMock.Setup(x => x.Get()).Returns(new EventMessages()); + + _service = new TestContentService( + _scopeProviderMock.Object, + _auditServiceMock.Object, + _eventMessagesFactoryMock.Object, + _loggerMock.Object); + } + + #region Audit Helper Method Tests + + [Test] + public void Audit_WithValidParameters_CreatesAuditEntry() + { + // Arrange + var userId = 1; + var objectId = 100; + var message = "Test audit message"; + + // Act + _service.TestAudit(AuditType.Save, userId, objectId, message); + + // Assert + _auditServiceMock.Verify(x => x.Write( + userId, + message, + It.IsAny(), + objectId), Times.Once); + } + + [Test] + public void Audit_WithNullMessage_UsesDefaultMessage() + { + // Arrange + var userId = 1; + var objectId = 100; + + // Act + _service.TestAudit(AuditType.Save, userId, objectId, null); + + // Assert + _auditServiceMock.Verify(x => x.Write( + userId, + It.Is(s => !string.IsNullOrEmpty(s)), + It.IsAny(), + objectId), Times.Once); + } + + #endregion + + #region Scope Provider Access Pattern Tests + + [Test] + public void CreateScope_ReturnsValidCoreScope() + { + // Arrange + var scopeMock = new Mock(); + _scopeProviderMock.Setup(x => x.CreateCoreScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(scopeMock.Object); + + // Act + var scope = _service.TestCreateScope(); + + // Assert + Assert.That(scope, Is.Not.Null); + _scopeProviderMock.Verify(x => x.CreateCoreScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public void CreateScope_WithAmbientScope_ReusesExisting() + { + // Arrange + var ambientScopeMock = new Mock(); + _scopeProviderMock.SetupGet(x => x.AmbientScope).Returns(ambientScopeMock.Object); + + // When ambient scope exists, CreateCoreScope should still be called + // but the scope provider handles the nesting + _scopeProviderMock.Setup(x => x.CreateCoreScope( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Returns(ambientScopeMock.Object); + + // Act + var scope = _service.TestCreateScope(); + + // Assert - scope should be the ambient scope (or nested in it) + Assert.That(scope, Is.Not.Null); + } + + #endregion + + #region Logger Injection Tests + + [Test] + public void Logger_IsInjectedCorrectly() + { + // Assert + Assert.That(_service.TestLogger, Is.Not.Null); + Assert.That(_service.TestLogger, Is.EqualTo(_loggerMock.Object)); + } + + [Test] + public void Logger_UsesCorrectCategoryName() + { + // The logger should be typed to the concrete service class + // This is verified by the generic type parameter + Assert.That(_service.TestLogger, Is.InstanceOf>()); + } + + #endregion + + #region Repository Access Tests + + [Test] + public void DocumentRepository_IsAccessibleWithinScope() + { + // This test validates that the base class provides access to the document repository + // The actual repository access pattern will be tested in integration tests + Assert.Pass("Repository access validated in integration tests"); + } + + #endregion + + /// + /// Test implementation of ContentServiceBase for unit testing. + /// + private class TestContentService : ContentServiceBase + { + public TestContentService( + ICoreScopeProvider scopeProvider, + IAuditService auditService, + IEventMessagesFactory eventMessagesFactory, + ILogger logger) + : base(scopeProvider, auditService, eventMessagesFactory, logger) + { + } + + // Expose protected members for testing + public void TestAudit(AuditType type, int userId, int objectId, string? message) + => Audit(type, userId, objectId, message); + + public ICoreScope TestCreateScope() => ScopeProvider.CreateCoreScope(); + + public ILogger TestLogger => Logger; + } + */ + + /// + /// v1.3: Tracking test that fails when ContentServiceBase is created. + /// When this test fails, uncomment all tests in this file and delete this placeholder. + /// + [Test] + public void ContentServiceBase_WhenCreated_UncommentTests() + { + // This tracking test uses reflection to detect when ContentServiceBase is created. + // When you see this test fail, it means Phase 1 has created ContentServiceBase. + // At that point: + // 1. Uncomment all the tests in this file (the commented section above) + // 2. Delete this tracking test + // 3. Verify all tests pass + + var type = Type.GetType("Umbraco.Cms.Infrastructure.Services.ContentServiceBase, Umbraco.Infrastructure"); + + Assert.That(type, Is.Null, + "ContentServiceBase now exists! Uncomment all tests in this file and delete this tracking test."); + } +}