instance = new ConfigurableClass(); ConfigurableAspect::reset(); } public function testAttributeArgumentsArePassedToConstructor(): void { $result = $this->instance->customConfigMethod(); // Verify the result was modified using the constructor arguments $this->assertEquals('PREFIX:value', $result); // Verify the execution log contains the constructor parameters $this->assertCount(2, ConfigurableAspect::$executionLog); $beforeLog = ConfigurableAspect::$executionLog[0]; $this->assertEquals('before', $beforeLog['event']); $this->assertEquals('PREFIX:', $beforeLog['prefix']); $this->assertEquals(10, $beforeLog['multiplier']); $afterLog = ConfigurableAspect::$executionLog[1]; $this->assertEquals('after', $afterLog['event']); $this->assertEquals('PREFIX:', $afterLog['prefix']); $this->assertEquals(10, $afterLog['multiplier']); } public function testDifferentMethodsCanHaveDifferentConfigurations(): void { $result1 = $this->instance->customConfigMethod(); ConfigurableAspect::reset(); $result2 = $this->instance->anotherMethod(); // First method uses prefix: 'PREFIX:', multiplier: 10 $this->assertEquals('PREFIX:value', $result1); // Second method uses prefix: 'BEFORE_', multiplier: 5 $this->assertEquals(35, $result2); // 7 * 5 // Verify execution log for second method $afterLog = ConfigurableAspect::$executionLog[1]; $this->assertEquals('BEFORE_', $afterLog['prefix']); $this->assertEquals(5, $afterLog['multiplier']); } public function testDisabledAspectDoesNotModifyResult(): void { $result = $this->instance->disabledMethod(); // enabled: false should prevent modification $this->assertEquals('should not be modified', $result); // No logs should be created when disabled $this->assertEmpty(ConfigurableAspect::$executionLog); } public function testDefaultConstructorArgumentsAreUsed(): void { $result = $this->instance->defaultConfigMethod(); // Default multiplier is 1, so 42 * 1 = 42 $this->assertEquals(42, $result); // Verify default values in execution log $beforeLog = ConfigurableAspect::$executionLog[0]; $this->assertEquals('default', $beforeLog['prefix']); $this->assertEquals(1, $beforeLog['multiplier']); } public function testConstructorArgumentsAffectBehavior(): void { // Test with multiplier $result = $this->instance->anotherMethod(); $this->assertEquals(35, $result); // 7 * 5 = 35 ConfigurableAspect::reset(); // Test with prefix $result = $this->instance->customConfigMethod(); $this->assertEquals('PREFIX:value', $result); } public function testEachConstructorArgumentIsActuallyUsed(): void { // Test 1: Verify 'prefix' argument is used ConfigurableAspect::reset(); $result = $this->instance->customConfigMethod(); $this->assertEquals('PREFIX:value', $result, 'prefix argument should prepend to string result'); $afterLog = ConfigurableAspect::$executionLog[1]; $this->assertEquals('PREFIX:', $afterLog['prefix'], 'prefix constructor argument should be stored and used'); // Test 2: Verify 'multiplier' argument is used ConfigurableAspect::reset(); $result = $this->instance->anotherMethod(); $this->assertEquals(35, $result, 'multiplier argument should multiply integer result (7 * 5 = 35)'); $afterLog = ConfigurableAspect::$executionLog[1]; $this->assertEquals(5, $afterLog['multiplier'], 'multiplier constructor argument should be stored and used'); // Test 3: Verify 'enabled' argument is used ConfigurableAspect::reset(); $result = $this->instance->disabledMethod(); $this->assertEquals('should not be modified', $result, 'enabled=false should prevent result modification'); $this->assertEmpty(ConfigurableAspect::$executionLog, 'enabled=false should prevent logging'); } public function testPartialConstructorArgumentsWithDefaults(): void { // disabledMethod uses only 'enabled: false', should use defaults for prefix and multiplier ConfigurableAspect::reset(); $this->instance->disabledMethod(); // Since enabled=false, no logs - but we can test with default values ConfigurableAspect::reset(); $result = $this->instance->defaultConfigMethod(); // Should use all defaults: prefix='default', multiplier=1, enabled=true $this->assertEquals(42, $result, 'default multiplier (1) should not change result'); $beforeLog = ConfigurableAspect::$executionLog[0]; $this->assertEquals('default', $beforeLog['prefix'], 'default prefix should be "default"'); $this->assertEquals(1, $beforeLog['multiplier'], 'default multiplier should be 1'); $afterLog = ConfigurableAspect::$executionLog[1]; $this->assertEquals('default', $afterLog['prefix'], 'default prefix should persist in after hook'); $this->assertEquals(1, $afterLog['multiplier'], 'default multiplier should persist in after hook'); } public function testAllThreeConstructorArgumentsSimultaneously(): void { ConfigurableAspect::reset(); // customConfigMethod uses: prefix='PREFIX:', multiplier=10, enabled=true (default) $result = $this->instance->customConfigMethod(); // Verify all three arguments are working together $this->assertEquals('PREFIX:value', $result); $beforeLog = ConfigurableAspect::$executionLog[0]; $this->assertEquals('before', $beforeLog['event']); $this->assertEquals('PREFIX:', $beforeLog['prefix'], 'First argument (prefix) should be used'); $this->assertEquals(10, $beforeLog['multiplier'], 'Second argument (multiplier) should be used'); // Third argument (enabled=true) is verified by the fact that logs exist $afterLog = ConfigurableAspect::$executionLog[1]; $this->assertEquals('after', $afterLog['event']); $this->assertEquals('PREFIX:', $afterLog['prefix'], 'First argument should persist in after hook'); $this->assertEquals(10, $afterLog['multiplier'], 'Second argument should persist in after hook'); // Verify the log exists (proving enabled=true was used) $this->assertCount(2, ConfigurableAspect::$executionLog, 'Third argument (enabled=true) should allow logging'); } }