logo SERENITY
Game Systems Foundation
Search Results for

    Show / Hide Table of Contents

    Class ServiceExtensionCreatorValidationTests

    EditMode tests for Validate(Input) and its pure preview helpers (ComposeServiceTypeName(Input) / ComposeSanitizedExtensionName(Input)). Aliased as Creator because the class name collides with its own namespace segment (Serenity.ServiceExtensionCreator.Editor.ServiceExtensionCreator). Every case that needs a real aggregate uses "Combo" (gameplay, virtualized, no InterfaceAdapters layer) from the live AggregateCatalog. Validate only reads the target folder (via AssetDatabase.IsValidFolder) and never writes into it, so one folder is created for the whole fixture instead of per-test — nothing here ever mutates it, and a shared folder means no repeated create/delete churn that could race an external file watcher (AV/cloud-sync).

    Inheritance
    object
    MetaFileRaceGuardedFixture
    ServiceExtensionCreatorValidationTests
    Inherited Members
    MetaFileRaceGuardedFixture.SuppressFailingLogMessagesForFixture()
    MetaFileRaceGuardedFixture.RestoreFailingLogMessages()
    MetaFileRaceGuardedFixture.SuppressFailingLogMessagesForTest()
    object.ToString()
    object.Equals(object)
    object.Equals(object, object)
    object.ReferenceEquals(object, object)
    object.GetHashCode()
    object.GetType()
    object.MemberwiseClone()
    Namespace: Serenity.ServiceExtensionCreator.Tests.Editor
    Assembly: Serenity.ServiceExtensionCreator.Tests.Editor.dll
    Syntax
    public class ServiceExtensionCreatorValidationTests : MetaFileRaceGuardedFixture

    Constructors

    ServiceExtensionCreatorValidationTests()

    Declaration
    public ServiceExtensionCreatorValidationTests()

    Methods

    ComposeCodeLayerName_InfrastructureFresh_ResolvesToInfrastructureRegardlessOfBaseLayer()

    The generated class for InfrastructureFresh lives under Infrastructure, exactly like InfrastructureSubclass — ComposeCodeLayerName(Input) is style-driven, not BaseLayer-driven, for the two Infrastructure styles.

    Declaration
    public void ComposeCodeLayerName_InfrastructureFresh_ResolvesToInfrastructureRegardlessOfBaseLayer()

    ComposeServiceTypeName_BusinessStyle_DoesNotStripUnityPrefix()

    Declaration
    public void ComposeServiceTypeName_BusinessStyle_DoesNotStripUnityPrefix()

    ComposeServiceTypeName_InfrastructureStyle_StripsSingleLeadingUnityPrefix()

    Declaration
    public void ComposeServiceTypeName_InfrastructureStyle_StripsSingleLeadingUnityPrefix()

    ComposeServiceTypeName_NullInput_ReturnsEmpty()

    Declaration
    public void ComposeServiceTypeName_NullInput_ReturnsEmpty()

    ComposeServiceTypeName_SubclassOfNonUnityBase_KeepsTheUserUnityPrefix()

    The double-prefix guard only strips a leading "Unity" when the composed name injects one of its own — Persistence's only eligible base is the non-Unity-prefixed PersistenceService, so a user extension name starting with "Unity" must survive intact.

    Declaration
    public void ComposeServiceTypeName_SubclassOfNonUnityBase_KeepsTheUserUnityPrefix()

    ComposeServiceTypeName_SubclassWithEmptyBaseName_ResolvesTheCanonicalBase()

    An empty SubclassBaseTypeName picks the canonical/first eligible base — the composed name stays exactly V1's {Name}Unity{Aggregate}Service shape.

    Declaration
    public void ComposeServiceTypeName_SubclassWithEmptyBaseName_ResolvesTheCanonicalBase()

    ComposeTypeName_SubclassStyleWithNonCanonicalBase_ComposesNameFromTheChosenBase()

    The Subclass type name is composed from the ACTUAL chosen base's name, not an invented Unity{Aggregate}Service — a non-canonical base like the fixture CustomComboBase composes {Name}CustomComboBase. Constructed-descriptor test: no production aggregate has a non-canonical eligible base yet, so the descriptor is built directly (ComposeTypeName is pure and never reads the catalog).

    Declaration
    public void ComposeTypeName_SubclassStyleWithNonCanonicalBase_ComposesNameFromTheChosenBase()

    OneTimeSetUp()

    Declaration
    public void OneTimeSetUp()

    OneTimeTearDown()

    Declaration
    public void OneTimeTearDown()

    ValidateSubclassBaseSelection_SimpleNameSharedByTwoBases_DemandsTheFullName()

    The base-selection resolver's ambiguity rule, pinned at the unit level with a constructed list — two fixture types sharing a simple name cannot both be matched by it, so the resolver demands the full name instead of first-picking.

    Declaration
    public void ValidateSubclassBaseSelection_SimpleNameSharedByTwoBases_DemandsTheFullName()

    Validate_AllowsBusinessDecoratorStyle()

    Declaration
    public void Validate_AllowsBusinessDecoratorStyle()

    Validate_AllowsBusinessFreshForPersistence()

    Business styles do not need a concrete Unity service, so Persistence must remain usable.

    Declaration
    public void Validate_AllowsBusinessFreshForPersistence()

    Validate_AllowsEmptyNamespace()

    Declaration
    public void Validate_AllowsEmptyNamespace()

    Validate_AllowsInfrastructureFreshForAggregateWithoutVirtualMembers()

    InfrastructureFresh is never gated on IsInfrastructureAvailable(AggregateDescriptor, out string) — unlike InfrastructureSubclass (see Validate_RejectsInfrastructureForAggregateWithoutVirtualMembers()), it must still validate cleanly for an aggregate with no virtual members at all.

    Declaration
    public void Validate_AllowsInfrastructureFreshForAggregateWithoutVirtualMembers()

    Validate_AllowsInfrastructureFreshForPersistence()

    InfrastructureFresh needs no concrete Unity service at all (unlike InfrastructureSubclass) — Persistence (no UnityPersistenceService, see Discover_Persistence_IsCoreInstalledWithNoConcreteUnityService()) must still validate cleanly under it.

    Declaration
    public void Validate_AllowsInfrastructureFreshForPersistence()

    Validate_AllowsInfrastructureSubclassForPersistenceViaTheBusinessPersistenceService()

    Persistence has no UnityPersistenceService, but the public business PersistenceService implements IPersistenceService with five public virtual operations — under the any-eligible-base rule it IS a valid subclass base, so the Subclass style is now available for Persistence (it was blocked when only the canonical Unity{X}Service counted). The composed type name follows the actual base: {Name}PersistenceService, no "Unity" prefix invented.

    Declaration
    public void Validate_AllowsInfrastructureSubclassForPersistenceViaTheBusinessPersistenceService()

    Validate_AllowsInfrastructureSubclassForVirtualizedAggregate()

    Declaration
    public void Validate_AllowsInfrastructureSubclassForVirtualizedAggregate()

    Validate_AllowsSubclassWithTheCanonicalBaseNamedExplicitly()

    Declaration
    public void Validate_AllowsSubclassWithTheCanonicalBaseNamedExplicitly()

    Validate_AllowsValidDottedNamespace()

    Declaration
    public void Validate_AllowsValidDottedNamespace()

    Validate_RejectsEmptyName()

    Declaration
    public void Validate_RejectsEmptyName()

    Validate_RejectsExcludedAggregate()

    Declaration
    public void Validate_RejectsExcludedAggregate()

    Validate_RejectsInfrastructureForAggregateWithoutVirtualMembers()

    Declaration
    public void Validate_RejectsInfrastructureForAggregateWithoutVirtualMembers()

    Validate_RejectsInvalidFolder()

    Declaration
    public void Validate_RejectsInvalidFolder()

    Validate_RejectsNamespaceInjectionPayload()

    Declaration
    public void Validate_RejectsNamespaceInjectionPayload()

    Validate_RejectsNamespaceSegmentStartingWithDigit()

    Declaration
    public void Validate_RejectsNamespaceSegmentStartingWithDigit()

    Validate_RejectsNamespaceWithLeadingDot()

    Declaration
    public void Validate_RejectsNamespaceWithLeadingDot()

    Validate_RejectsNamespaceWithTrailingDot()

    Declaration
    public void Validate_RejectsNamespaceWithTrailingDot()

    Validate_RejectsNullInput()

    Declaration
    public void Validate_RejectsNullInput()

    Validate_RejectsTypeNameCollisionWithExistingRealType()

    Validate's collision check compares against the layered namespace it will actually generate into ({RootNamespace}.{CodeLayer}.Services), not the raw NamespaceOverride — so this test collides against a fixture type declared right below, in this same file, whose namespace was chosen to be exactly the composed namespace for the input below, rather than depending on a real Serenity aggregate's namespace shape (which no longer has any reason to match the generated layout).

    Declaration
    public void Validate_RejectsTypeNameCollisionWithExistingRealType()

    Validate_RejectsUnknownAggregate()

    Declaration
    public void Validate_RejectsUnknownAggregate()

    Validate_RejectsUnknownSubclassBaseNameListingTheAvailableBases()

    Declaration
    public void Validate_RejectsUnknownSubclassBaseNameListingTheAvailableBases()
    In this article
    © 2026 Serenity. All Rights Reserved