如何在测试中正确使用Symfony验证器?

时间:2018-06-02 08:59:52

标签: php symfony validation mocking phpunit

我有一个服务类:

class OutletTableWriter
{
    private $validator;

    private $entityManager;

    public function __construct(ValidatorInterface $validator, EntityManagerInterface $em)
    {
        $this->validator    = $validator;
        $this->em           = $em;

    }
// inserts outlet to db
    public function insertOutlet($outletName, $buildingName = null, $propertyNumber, $streetName, $area, $town, $contactNumber, $postcode)
    {
        $outlet = new Outlet();
        $outlet->setOutletName($outletName);
        $outlet->setBuildingName($buildingName);
        $outlet->setPropertyNumber($propertyNumber);
        $outlet->setStreetName($streetName);
        $outlet->setArea($area);
        $outlet->setTown($town);
        $outlet->setContactNumber($contactNumber);
        $outlet->setPostCode($postcode);
        $outlet->setIsActive(0);

        // $validator = $this->get('validator'); // validate constraints
        $errors = $this->validator->validate($outlet);
        if (count($errors) > 0) {
            $response = new Response('', 422, array('content-type' => 'text/html'));

            $errorsString = (string) $errors;
            $response->setContent($errorsString);
            return $response;
        }

        $this->em->persist($outlet);
        $this->em->flush(); // save

        return new Response('Outlet #'.$outlet->getId().' has been successfully saved.', 201);
    }

这可以按预期工作。但是,在测试此类的功能时,我遇到了问题。我有以下测试方法:

public function testUnsuccessfulInsertOutlet()
    {
        $mockValidator  = $this->getMockBuilder(ValidatorInterface::class)
            ->disableOriginalConstructor()
            ->getMock();

        $mockEm         = $this->getMockBuilder(EntityManagerInterface::class)
            ->disableOriginalConstructor()->getMock();


        $outletTableWriter  = new OutletTableWriter($mockValidator, $mockEm);
        $response           = $outletTableWriter->insertOutlet(
            '', '', '', '', '', '', 'EXX 1XX'
        );

        $this->assertEquals(422, $response->getStatusCode());
    }

验证器应该失败,而不是似乎没有进行验证(返回201响应)。我觉得它与我嘲弄验证器类的方式有关(它甚至需要被模拟吗? - 我尝试只传入类本身的一个对象,这导致了以下异常:{{ 1}}。

我使用的是Symfony 3.4.6。

欣赏任何建议。

2 个答案:

答案 0 :(得分:1)

我根据用户的经验让测试类中的验证工具正常工作:https://github.com/symfony/symfony-docs/issues/6532

因此,在我的测试中,我进行了以下更改(实例化验证器时):

use Symfony\Component\Validator\Validation;

$this->validator    = Validation::createValidatorBuilder()->enableAnnotationMapping()->getValidator();

答案 1 :(得分:0)

我认为你必须告诉验证器模拟在调用方法'validate'时要做什么。 e.g。

    $errors = ['some_error'];
    $validatorMock = $this->createMock(ValidatorInterface::class);
    $validatorMock->expects($this->once())->method('validate')->with($outlet)->willReturn($errors);