assertInstanceOf(Resource::class, $resource); $this->assertSame($uri, $resource->uri); } public function testConstructorInvalid(): void { $uri = '/list-books'; $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Invalid resource URI: "/list-books" must be a valid URI with a scheme and optional path.'); $resource = new Resource( uri: $uri, name: 'list-books', ); } public function testFromArrayValid(): void { $resource = Resource::fromArray([ 'uri' => self::VALID_URI, 'name' => 'list-books', ]); $this->assertInstanceOf(Resource::class, $resource); $this->assertSame(self::VALID_URI, $resource->uri); $this->assertSame('list-books', $resource->name); $this->assertNull($resource->description); $this->assertNull($resource->meta); } #[DataProvider('provideInvalidResources')] public function testFromArrayInvalid(array $input, string $expectedExceptionMessage): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage($expectedExceptionMessage); Resource::fromArray($input); } public static function provideInvalidResources(): iterable { yield 'missing uri' => [[], 'Invalid or missing "uri" in Resource data.']; yield 'missing name' => [ ['uri' => self::VALID_URI], 'Invalid or missing "name" in Resource data.', ]; yield 'meta' => [ [ 'uri' => self::VALID_URI, 'name' => 'list-books', '_meta' => 'foo', ], 'Invalid "_meta" in Resource data.', ]; } }