Validate that type loader always returns the same type instance as referenced in other parts of the schema

This commit is contained in:
Vladimir Razuvaev 2017-08-14 22:32:07 +07:00
parent b9d3a11785
commit 8817d54e83
2 changed files with 38 additions and 1 deletions

View File

@ -358,7 +358,6 @@ class Schema
return isset($typeMap[$typeName]) ? $typeMap[$typeName] : null; return isset($typeMap[$typeName]) ? $typeMap[$typeName] : null;
} }
/** /**
* @throws InvariantViolation * @throws InvariantViolation
*/ */
@ -392,6 +391,15 @@ class Schema
$this->assertImplementsIntarface($type, $iface); $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.'
);
}
} }
} }

View File

@ -2698,6 +2698,35 @@ class ValidationTest extends \PHPUnit_Framework_TestCase
$schema->assertValid(); $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) private function assertEachCallableThrows($closures, $expectedError)
{ {