Repository: symfony/symfony
File: src/Symfony/Component/Validator/Tests/Constraints/NotCompromisedPasswordValidatorTest.php (PHP)

Code before:
    {
        $this->expectException(ExceptionInterface::class);
        $this->expectExceptionMessage('Problem contacting the Have I been Pwned API.');
        $this->validator->validate(self::PASSWORD_TRIGGERING_AN_ERROR, new NotCompromisedPassword());
    }

    /**
     * @dataProvider provideErrorSkippingConstraints
     */
    public function testApiErrorSkipped(NotCompromisedPassword $constraint)
    {
        $this->validator->validate(self::PASSWORD_TRIGGERING_AN_ERROR, $constraint);
        $this->assertTrue(true); // No exception have been thrown
    }

    public static function provideErrorSkippingConstraints(): iterable
    {
        yield 'Doctrine style' => [new NotCompromisedPassword(['skipOnError' => true])];
        yield 'named arguments' => [new NotCompromisedPassword(skipOnError: true)];
    }

    private function createHttpClientStub(?string $returnValue = null): HttpClientInterface
    {
        return new MockHttpClient(function ($method, $url) {
            if (self::PASSWORD_TRIGGERING_AN_ERROR_RANGE_URL === $url) {
                throw new class('Problem contacting the Have I been Pwned API.') extends \Exception implements ServerExceptionInterface {
                    public function getResponse(): ResponseInterface
                    {
                        throw new \RuntimeException('Not implemented');
                    }
                };
            }

            return new MockResponse($returnValue ?? implode("\r\n", self::RETURN));
        });
    }

    private function createHttpClientStubCustomEndpoint($expectedEndpoint): HttpClientInterface
    {
        return new MockHttpClient(function ($method, $url) use ($expectedEndpoint) {
            $this->assertSame('GET', $method);
            $this->assertSame($expectedEndpoint, $url);

            return new MockResponse(implode("\r\n", self::RETURN));
        });
    }
}


Review comment (suggestion):
Why not throwing directly the class of the http-client component (the usage of MockHttpClient introduced a hard dependency anyway)

Code after:
        $this->validator->validate(self::PASSWORD_TRIGGERING_AN_ERROR, new NotCompromisedPassword());
    }

    /**
     * @dataProvider provideErrorSkippingConstraints
     */
    public function testApiErrorSkipped(NotCompromisedPassword $constraint)
    {
        self::expectNotToPerformAssertions();

        $this->validator->validate(self::PASSWORD_TRIGGERING_AN_ERROR, $constraint);
    }

    public static function provideErrorSkippingConstraints(): iterable
    {
        yield 'Doctrine style' => [new NotCompromisedPassword(['skipOnError' => true])];
        yield 'named arguments' => [new NotCompromisedPassword(skipOnError: true)];
    }

    private function createHttpClientStub(?string $returnValue = null): HttpClientInterface
    {
        return new MockHttpClient(function ($method, $url) use ($returnValue) {
            if (self::PASSWORD_TRIGGERING_AN_ERROR_RANGE_URL !== $url) {
                return new MockResponse($returnValue ?? implode("\r\n", self::RETURN));
            }
        });
    }

    private function createHttpClientStubCustomEndpoint($expectedEndpoint): HttpClientInterface
    {
        return new MockHttpClient(function ($method, $url) use ($expectedEndpoint) {
            $this->assertSame('GET', $method);
            $this->assertSame($expectedEndpoint, $url);

            return new MockResponse(implode("\r\n", self::RETURN));
        });
    }
}