Symfony/PhpUnit - 如何测试服务中是否抛出异常

Symfony/PhpUnit - How to test that an Exception is throws or not in a Service

我是测试新手,我想测试我的 ValidatorService,它会在实体数据无效时抛出 InvalidDataException

我的 ValidatorServiceTest 函数:

    public function testValidatorForUser()
    {
        $validatorMock = $this->createMock(ValidatorInterface::class);
        $contraintViolationMock = $this->createMock(ConstraintViolationListInterface::class);

        $validatorMock->expects($this->once())
            ->method('validate')
            ->with()
            ->willReturn($contraintViolationMock);

        $validatorService = new ValidatorService($validatorMock);
        $user = new User();
        $user->setEmail('test');

        $validatorService->validate($user);
        $this->expectException(InvalidDataException::class);
    }

我的 ValidatorService :

class ValidatorService
{
    /**
     * @var ValidatorInterface
     */
    private ValidatorInterface $validator;

    public function __construct(ValidatorInterface $validator)
    {
        $this->validator = $validator;
    }

    /**
     * @param $value
     * @param null $constraints
     * @param null $groups
     * @throws InvalidDataException
     */
    public function validate($value, $constraints = null, $groups = null)
    {
        $errors = $this->validator->validate($value, $constraints, $groups);

        if (count($errors) > 0) {
            throw new InvalidDataException($errors);
        }
    }
}

我的用户实体:

/**
 * @ORM\Entity(repositoryClass=UserRepository::class)
 * @ORM\Table(name="`user`")
 * @UniqueEntity(fields="email", errorPath="email", message="user.email.unique")
 * @UniqueEntity(fields="username", errorPath="username", message="user.username.unique")
 */
class User implements UserInterface
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private ?int $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     * @JMS\Type("string")
     * @JMS\Groups({"api"})
     * @Assert\NotBlank(message="user.email.not_blank")
     * @Assert\Email(message="user.email.email")
     */
    private string $email;

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     * @JMS\Type("string")
     * @Assert\NotBlank(message="user.password.not_blank")
     * @Assert\Length(min=8, minMessage="user.password.length.min")
     */
    private string $password;

    /**
     * @JMS\Type("string")
     * @Assert\NotBlank(message="user.confirm_password.not_blank")
     * @Assert\EqualTo(propertyPath="password", message="user.confirm_password.equal_to")
     */
    private string $confirmPassword;

   ...
   ...

我有这个错误

1) App\Tests\Service\Validator\ValidatorServiceTest::testValidatorForUser
Failed asserting that exception of type "App\Exception\InvalidDataException" is thrown.

如何测试是否出现异常?

已解决:

问题出在我的 $contraintViolationMock 上,它总是返回空数据。 我必须之前检索违规并测试它是否与模拟违规相匹配。我认为,这是比手动创建 ConstraintViolationList 更简单的解决方案。 如果你有更好的解决方案,我会采纳。

    public function testValidatorForUser()
    {
        $user = new User();
        $user->setEmail('test');
        $validator = self::$container->get(ValidatorInterface::class);
        $violations = $validator->validate($user);

        $validatorMock = $this->createMock(ValidatorInterface::class);

        $validatorMock->expects($this->once())
            ->method('validate')
            ->willReturn($violations);

        $this->expectException(InvalidDataException::class);

        $validatorService = new ValidatorService($validatorMock);
        $validatorService->validate($user);
    }