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

Posted

技术标签:

【中文标题】Symfony/PhpUnit - 如何测试服务中是不是抛出异常【英文标题】:Symfony/PhpUnit - How to test that an Exception is throws or not in a ServiceSymfony/PhpUnit - 如何测试服务中是否抛出异常 【发布时间】:2021-06-20 10:30:33 【问题描述】:

我是测试的初学者,我想测试我的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.

如何测试异常是否抛出?

【问题讨论】:

在测试中将调用换成 validate() expectException() - 如果它已经发生了,你就无法期待。 我有同样的错误。 我已经复制了你的代码并尽我所能进行了测试——你没有犯任何错误,$errors 是空的,所以没有抛出任何东西。 我更新了主帖并添加了User实体。而且我直接用$validator = self::$container->get(ValidatorInterface::class); $errors = $validator->validate($user)试了一下,$errors 不为空。 【参考方案1】:

已解决:

问题在于我的$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);
    

【讨论】:

以上是关于Symfony/PhpUnit - 如何测试服务中是不是抛出异常的主要内容,如果未能解决你的问题,请参考以下文章

Symfony PHPUnit 测试不验证用户

测试结束时删除测试数据库(Symfony / PHP Unit)

Symfony PHPUnit问题安装Xdebug for --coverage-html

PHPUnit错误:找不到类

如何在 DevOps 上针对多个服务运行集成测试?

如何对 Windows 服务中托管的 wcf 服务进行负载/压力测试?