registration: Allow overriding attributes in tests
authorKunal Mehta <legoktm@member.fsf.org>
Sat, 12 Jan 2019 19:35:02 +0000 (11:35 -0800)
committerKunal Mehta <legoktm@member.fsf.org>
Mon, 14 Jan 2019 20:47:10 +0000 (12:47 -0800)
ExtensionRegistry is a rather special singleton that can't use the normal
MediaWikiServices reset due to its early initialization, so introduce
a ->setAttributeForTest method to override attributes that are typically
loaded from extension.json.

Bug: T200013
Change-Id: I9e62a02ed2044c847e9ab2dcdfab094001f88986

includes/registration/ExtensionRegistry.php
tests/phpunit/includes/registration/ExtensionRegistryTest.php

index e462a0b..e3bd542 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 use Composer\Semver\Semver;
+use Wikimedia\ScopedCallback;
 
 /**
  * ExtensionRegistry class
@@ -76,6 +77,13 @@ class ExtensionRegistry {
         */
        protected $attributes = [];
 
+       /**
+        * Attributes for testing
+        *
+        * @var array
+        */
+       protected $testAttributes = [];
+
        /**
         * @var ExtensionRegistry
         */
@@ -412,7 +420,29 @@ class ExtensionRegistry {
         * @return array
         */
        public function getAttribute( $name ) {
-               return $this->attributes[$name] ?? [];
+               return $this->testAttributes[$name] ??
+                       $this->attributes[$name] ?? [];
+       }
+
+       /**
+        * Force override the value of an attribute during tests
+        *
+        * @param string $name Name of attribute to override
+        * @param array $value Value to set
+        * @return ScopedCallback to reset
+        * @since 1.33
+        */
+       public function setAttributeForTest( $name, array $value ) {
+               if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
+                       throw new RuntimeException( __METHOD__ . ' can only be used in tests' );
+               }
+               if ( isset( $this->testAttributes[$name] ) ) {
+                       throw new Exception( "The attribute '$name' has already been overridden" );
+               }
+               $this->testAttributes[$name] = $value;
+               return new ScopedCallback( function () use ( $name ) {
+                       unset( $this->testAttributes[$name] );
+               } );
        }
 
        /**
index 1baa79c..5de1b0c 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use Wikimedia\ScopedCallback;
+
 /**
  * @covers ExtensionRegistry
  */
@@ -399,4 +401,28 @@ class ExtensionRegistryTest extends MediaWikiTestCase {
                        ],
                ];
        }
+
+       public function testSetAttributeForTest() {
+               $registry = new ExtensionRegistry();
+               $registry->queue( "{$this->dataDir}/good.json" );
+               $registry->loadFromQueue();
+               // Sanity check that it worked
+               $this->assertSame( [ 'test' ], $registry->getAttribute( 'FooBarAttr' ) );
+               $reset = $registry->setAttributeForTest( 'FooBarAttr', [ 'override' ] );
+               // overridden properly
+               $this->assertSame( [ 'override' ], $registry->getAttribute( 'FooBarAttr' ) );
+               ScopedCallback::consume( $reset );
+               // reset properly
+               $this->assertSame( [ 'test' ], $registry->getAttribute( 'FooBarAttr' ) );
+       }
+
+       /**
+        * @expectedException Exception
+        * @expectedExceptionMessage The attribute 'foo' has already been overridden
+        */
+       public function testSetAttributeForTestDuplicate() {
+               $registry = new ExtensionRegistry();
+               $reset1 = $registry->setAttributeForTest( 'foo', [ 'val1' ] );
+               $reset2 = $registry->setAttributeForTest( 'foo', [ 'val2' ] );
+       }
 }