有没有人有一个很好的方法来对Symfony2中的实体验证约束进行单元测试?
理想情况下,我希望能够在单元测试中访问依赖注入容器,这样我就可以访问验证器服务.一旦我有验证器服务,我就可以手动运行它:
$errors = $validator->validate($entity);
Run Code Online (Sandbox Code Playgroud)
我可以扩展WebTestCase
然后client
根据文档创建一个到达容器然而它感觉不对.该WebTestCase
和client
在文档读取为更多的设备来测试的行为作为一个整体,因此感觉破碎用它来单元测试的实体.
那么,有没有人知道如何a)获取容器或b)在单元测试中创建验证器?
Kas*_*een 63
好吧,因为这得到两票我猜其他人都感兴趣.
我决定拿出我的铲子并且惊喜(到目前为止,无论如何),这根本不是很困难.
我记得每个Symfony2组件都可以在独立模式下使用,因此我可以自己创建验证器.
查看文档:https://github.com/symfony/Validator/blob/master/ValidatorFactory.php
我意识到,由于有一个ValidatorFactory,创建一个验证器是微不足道的(特别是我通过注释完成的验证,虽然如果你查看我上面链接的页面上的docblock,你也会找到验证xml和yml的方法).
第一:
# Symfony >=2.1
use Symfony\Component\Validator\Validation;
# Symfony <2.1
use Symfony\Component\Validator\ValidatorFactory;
Run Code Online (Sandbox Code Playgroud)
然后:
# Symfony >=2.1
$validator = Validation::createValidatorBuilder()->enableAnnotationMapping()->getValidator();
# Symfony <2.1
$validator = ValidatorFactory::buildDefault()->getValidator();
$errors = $validator->validate($entity);
$this->assertEquals(0, count($errors));
Run Code Online (Sandbox Code Playgroud)
我希望这有助于其他任何良心不允许他们使用WebTestCase的人;).
Mat*_*att 38
我们最终会推出自己的基本测试用例,以便从测试用例中访问依赖容器.这里的课程有问题:
<?php
namespace Application\AcmeBundle\Tests;
// This assumes that this class file is located at:
// src/Application/AcmeBundle/Tests/ContainerAwareUnitTestCase.php
// with Symfony 2.0 Standard Edition layout. You may need to change it
// to fit your own file system mapping.
require_once __DIR__.'/../../../../app/AppKernel.php';
class ContainerAwareUnitTestCase extends \PHPUnit_Framework_TestCase
{
protected static $kernel;
protected static $container;
public static function setUpBeforeClass()
{
self::$kernel = new \AppKernel('dev', true);
self::$kernel->boot();
self::$container = self::$kernel->getContainer();
}
public function get($serviceId)
{
return self::$kernel->getContainer()->get($serviceId);
}
}
Run Code Online (Sandbox Code Playgroud)
使用此基类,您现在可以在测试方法中执行此操作以访问验证器服务:
$validator = $this->get('validator');
Run Code Online (Sandbox Code Playgroud)
我们决定使用静态函数而不是类构造函数,但是您可以轻松地更改行为以将内核直接实例化到构造函数中,而不是依赖于setUpBeforeClass
PHPUnit提供的静态方法.
另外,请记住,测试用例中的每个单独测试方法都不会彼此隔离,因为容器是针对整个测试用例共享的.对容器进行修改可能会对您的其他测试方法产生影响,但如果您只访问该validator
服务则不应该这样.但是,通过这种方式,测试用例将运行得更快,因为您不需要为每个测试方法实例化和引导新内核.
为了便于参考,我们从这篇博文中找到了本课程的灵感.它是用法语写的,但我更愿意归功于它属于谁:)
问候,
马特
And*_*mko 27
我喜欢Kasheens的答案,但它不再适用于Symfony 2.3.几乎没有变化:
use Symfony\Component\Validator\Validation;
Run Code Online (Sandbox Code Playgroud)
和
$validator = Validation::createValidatorBuilder()->getValidator();
Run Code Online (Sandbox Code Playgroud)
如果要验证Annotations,请使用如下所示的enableAnnotationMapping():
$validator = Validation::createValidatorBuilder()->enableAnnotationMapping()->getValidator();
Run Code Online (Sandbox Code Playgroud)
其余的保持不变:
$errors = $validator->validate($entity);
$this->assertEquals(0, count($errors));
Run Code Online (Sandbox Code Playgroud)
使用Symfony 2.8,您现在可以通过AbstractConstraintValidatorTest
以下方式使用该类:
<?php
namespace AppBundle\Tests\Constraints;
use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest;
use AppBundle\Constraints\MyConstraint;
use AppBundle\Constraints\MyConstraintValidator;
use AppBundle\Entity\MyEntity;
use Symfony\Component\Validator\Validation;
class MyConstraintValidatorTest extends AbstractConstraintValidatorTest
{
protected function getApiVersion()
{
return Validation::API_VERSION_2_5;
}
protected function createValidator()
{
return new MyConstraintValidator();
}
public function testIsValid()
{
$this->validator->validate(null, new MyEntity());
$this->assertNoViolation();
}
public function testNotValid()
{
$this->assertViolationRaised(new MyEntity(), MyConstraint::SOME_ERROR_NAME);
}
}
Run Code Online (Sandbox Code Playgroud)
你有一个很好的样本与IpValidatorTest类
小智 5
对于 Symfony 4, /sf/answers/2931926301/中的答案必须稍作更改:
使用ConstraintValidatorTestCase
而不是AbstractConstraintValidatorTest
.
归档时间: |
|
查看次数: |
23032 次 |
最近记录: |