diff --git a/src/Type/Schema.php b/src/Type/Schema.php index 8505557..74a961b 100644 --- a/src/Type/Schema.php +++ b/src/Type/Schema.php @@ -358,7 +358,6 @@ class Schema return isset($typeMap[$typeName]) ? $typeMap[$typeName] : null; } - /** * @throws InvariantViolation */ @@ -392,6 +391,15 @@ class Schema $this->assertImplementsIntarface($type, $iface); } } + + // Make sure type loader returns the same instance as registered in other places of schema + if ($this->config->typeLoader) { + Utils::invariant( + $this->loadType($name) === $type, + "Type loader returns different instance for {$name} than field/argument definitions. ". + 'Make sure you always return the same instance for the same type name.' + ); + } } } diff --git a/tests/Type/ValidationTest.php b/tests/Type/ValidationTest.php index db476e8..3aa93e4 100644 --- a/tests/Type/ValidationTest.php +++ b/tests/Type/ValidationTest.php @@ -2698,6 +2698,35 @@ class ValidationTest extends \PHPUnit_Framework_TestCase $schema->assertValid(); } + public function testRejectsDifferentInstancesOfTheSameType() + { + // Invalid: always creates new instance vs returning one from registry + $typeLoader = function($name) use (&$typeLoader) { + switch ($name) { + case 'Query': + return new ObjectType([ + 'name' => 'Query', + 'fields' => [ + 'test' => Type::string() + ] + ]); + default: + return null; + } + }; + + $schema = new Schema([ + 'query' => $typeLoader('Query'), + 'typeLoader' => $typeLoader + ]); + $this->setExpectedException( + InvariantViolation::class, + 'Type loader returns different instance for Query than field/argument definitions. '. + 'Make sure you always return the same instance for the same type name.' + ); + $schema->assertValid(); + } + private function assertEachCallableThrows($closures, $expectedError) {