实体的 @Assert\NotBlank() 注释等约束在单元测试中不起作用,这会给出语义或自动加载错误
Constraints like @Assert\NotBlank() annotation for entities does not work in unit test which gives semantical or auto loaded error
当我 运行 单元测试时,它给出了以下约束错误
[语义错误] 属性 AppBundle\Entity\User::$username 中的注释“@Symfony\Component\Validator\Constraints\NotBlank”不存在,或无法自动加载.
这是我的实体
User.class
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
/**
* Class User
* @package AppBundle\Entity
*
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* @ORM\Table(name="user")
* @ORM\HasLifecycleCallbacks()
*
*/
class User implements AdvancedUserInterface, \Serializable
{
/** @var double
* @ORM\Column(type="bigint", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
* @ORM\Column(type="string", length=60, unique=true)
* @Assert\NotBlank()
* @Assert\Email()
*/
private $username;
/**
* @ORM\Column(type="string", length=64)
*/
private $password;
/**
* @Assert\NotBlank()
* @Assert\Length(max=4096)
*/
private $plainPassword;
/**
* @var string
* @ORM\Column(name="fullname", type="string", length=100, nullable=false)
* @Assert\NotBlank()
*/
protected $fullname;
/**
* @var \DateTime
* @ORM\Column(name="createdat", type="datetime", nullable=true)
*/
protected $createdat;
/**
* @var \DateTime
* @ORM\Column(name="modifiedat", type="datetime", nullable=true)
*/
protected $modifiedat;
/**
* @ORM\Column(type="boolean", options={"default" = 1}, nullable=false)
*/
private $isactive = true;
public function __construct()
{
$this->updatedTimestamps();
}
/**
* Now we tell doctrine that before we persist or update we call the updatedTimestamps() function.
*
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function updatedTimestamps()
{
$this->setModifiedat(new \DateTime(date('Y-m-d H:i:s')));
if($this->getCreatedat() == null)
{
$this->setCreatedat(new \DateTime(date('Y-m-d H:i:s')));
}
}
public function getUsername()
{
return $this->username;
}
public function getSalt()
{
// you *may* need a real salt depending on your encoder
// see section on salt below
return '';
}
public function getPassword()
{
return $this->password;
}
public function getRoles()
{
return array('ROLE_USER');
}
public function eraseCredentials()
{
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isactive;
}
/** @see \Serializable::serialize() */
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
$this->isactive
));
}
/** @see \Serializable::unserialize() */
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
$this->isactive
) = unserialize($serialized);
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* @param string $username
*
* @return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Set password
*
* @param string $password
*
* @return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set isactive
*
* @param boolean $isactive
*
* @return User
*/
public function setIsactive($isactive)
{
$this->isactive = $isactive;
return $this;
}
/**
* Get isactive
*
* @return boolean
*/
public function getIsactive()
{
return $this->isactive;
}
/**
* @return mixed
*/
public function getPlainPassword()
{
return $this->plainPassword;
}
/**
* @param mixed $plainPassword
*/
public function setPlainPassword($plainPassword)
{
$this->plainPassword = $plainPassword;
}
/**
* Set fullname
*
* @param string $fullname
*
* @return User
*/
public function setFullname($fullname)
{
$this->fullname = $fullname;
return $this;
}
/**
* Get fullname
*
* @return string
*/
public function getFullname()
{
return $this->fullname;
}
/**
* Set createdat
*
* @param \DateTime $createdat
*
* @return User
*/
public function setCreatedat($createdat)
{
$this->createdat = $createdat;
return $this;
}
/**
* Get createdat
*
* @return \DateTime
*/
public function getCreatedat()
{
return $this->createdat;
}
/**
* Set modifiedat
*
* @param \DateTime $modifiedat
*
* @return User
*/
public function setModifiedat($modifiedat)
{
$this->modifiedat = $modifiedat;
return $this;
}
/**
* Get modifiedat
*
* @return \DateTime
*/
public function getModifiedat()
{
return $this->modifiedat;
}
/**
* The __toString method allows a class to decide how it will react when it is converted to a string.
*
* @return string
* @link http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring
*/
function __toString()
{
return "id: ". $this->id ." email: ". $this->username . " fullname: ". $this->fullname . " isactive: ". $this->isactive .
" createdat: ". $this->createdat->format('Y-m-d H:i:s') ." updatedat: ". $this->modifiedat->format('Y-m-d H:i:s');
}
}
这是我的单元测试classes:
TestBase.class
namespace tests\AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\DependencyInjection\Container;
use Doctrine\Common\Annotations\AnnotationRegistry;
use AppKernel;
AnnotationRegistry::registerFile("../../../vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php");
require_once __DIR__ . "/../../../vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php";
class TestBase extends \PHPUnit_Framework_TestCase
{
/**
* @var Application
*/
protected $application;
/**
* @var \Doctrine\ORM\EntityManager
*/
protected $entityManager;
/**
* @var \AppKernel
*/
protected $kernel;
/**
* @var Container
*/
protected $container;
protected function setUp()
{
$this->kernel = new AppKernel("test", true);
$this->kernel->boot();
$this->application = new Application($this->kernel);
$this->application->setAutoExit(false);
// Store the container and the entity manager in test case properties
$this->container = $this->kernel->getContainer();
$this->entityManager = $this->container->get("doctrine")->getManager();
if(is_null($this->entityManager)){
print("upssss entitiy manager is null :(");
}
parent::setUp();
}
public function tearDown()
{
// Shutdown the kernel.
$this->kernel->shutdown();
parent::tearDown();
}
}
我在这里测试我的用户 class 只是打印数据库..
UserTest.class
namespace tests\AppBundle\Controller;
require_once ("TestBase.php");
class UserTest extends TestBase
{
protected function setUp()
{
parent::setUp();
}
public function tearDown()
{
parent::tearDown();
}
//generic method to list the users
public function listUsers($users ){
echo EOL, EOL;
foreach($users as $user){
echo $user, EOL;
}
echo EOL, EOL;
}
public function testListUsers(){
$users = $this->entityManager->getRepository('AppBundle:User')->findAll();
$this->assertGreaterThan(1, count($users));
$this->listUsers($users);
}
}
顺便说一下,当我不使用 @Assert\NotBlank() 时它会起作用
所以从代码的角度来看完全没有问题......我猜它只是关于单元测试时的自动加载..
我真的被那个卡住了 2 周..
好的,我找到了答案..
当我把test改成dev 在 AppKernel 中有效
旧的是这样的:
$this->kernel = new AppKernel("test", true);
解决方案
$this->kernel = new AppKernel("dev", true);
虽然
我没有改变我的AppKernel.php
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
define('EOL',(PHP_SAPI == 'cli') ? PHP_EOL : '<br />');
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = [
new Liuggio\ExcelBundle\LiuggioExcelBundle(),
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new AppBundle\AppBundle(),
];
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
}
return $bundles;
}
public function getRootDir()
{
return __DIR__;
}
public function getCacheDir()
{
return dirname(__DIR__).'/var/cache/'.$this->getEnvironment();
}
public function getLogDir()
{
return dirname(__DIR__).'/var/logs';
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml');
}
}
当我 运行 单元测试时,它给出了以下约束错误
[语义错误] 属性 AppBundle\Entity\User::$username 中的注释“@Symfony\Component\Validator\Constraints\NotBlank”不存在,或无法自动加载.
这是我的实体
User.class
namespace AppBundle\Entity;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\AdvancedUserInterface;
/**
* Class User
* @package AppBundle\Entity
*
* @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
* @ORM\Table(name="user")
* @ORM\HasLifecycleCallbacks()
*
*/
class User implements AdvancedUserInterface, \Serializable
{
/** @var double
* @ORM\Column(type="bigint", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @var string
* @ORM\Column(type="string", length=60, unique=true)
* @Assert\NotBlank()
* @Assert\Email()
*/
private $username;
/**
* @ORM\Column(type="string", length=64)
*/
private $password;
/**
* @Assert\NotBlank()
* @Assert\Length(max=4096)
*/
private $plainPassword;
/**
* @var string
* @ORM\Column(name="fullname", type="string", length=100, nullable=false)
* @Assert\NotBlank()
*/
protected $fullname;
/**
* @var \DateTime
* @ORM\Column(name="createdat", type="datetime", nullable=true)
*/
protected $createdat;
/**
* @var \DateTime
* @ORM\Column(name="modifiedat", type="datetime", nullable=true)
*/
protected $modifiedat;
/**
* @ORM\Column(type="boolean", options={"default" = 1}, nullable=false)
*/
private $isactive = true;
public function __construct()
{
$this->updatedTimestamps();
}
/**
* Now we tell doctrine that before we persist or update we call the updatedTimestamps() function.
*
* @ORM\PrePersist
* @ORM\PreUpdate
*/
public function updatedTimestamps()
{
$this->setModifiedat(new \DateTime(date('Y-m-d H:i:s')));
if($this->getCreatedat() == null)
{
$this->setCreatedat(new \DateTime(date('Y-m-d H:i:s')));
}
}
public function getUsername()
{
return $this->username;
}
public function getSalt()
{
// you *may* need a real salt depending on your encoder
// see section on salt below
return '';
}
public function getPassword()
{
return $this->password;
}
public function getRoles()
{
return array('ROLE_USER');
}
public function eraseCredentials()
{
}
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked()
{
return true;
}
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled()
{
return $this->isactive;
}
/** @see \Serializable::serialize() */
public function serialize()
{
return serialize(array(
$this->id,
$this->username,
$this->password,
$this->isactive
));
}
/** @see \Serializable::unserialize() */
public function unserialize($serialized)
{
list (
$this->id,
$this->username,
$this->password,
$this->isactive
) = unserialize($serialized);
}
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set username
*
* @param string $username
*
* @return User
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* Set password
*
* @param string $password
*
* @return User
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Set isactive
*
* @param boolean $isactive
*
* @return User
*/
public function setIsactive($isactive)
{
$this->isactive = $isactive;
return $this;
}
/**
* Get isactive
*
* @return boolean
*/
public function getIsactive()
{
return $this->isactive;
}
/**
* @return mixed
*/
public function getPlainPassword()
{
return $this->plainPassword;
}
/**
* @param mixed $plainPassword
*/
public function setPlainPassword($plainPassword)
{
$this->plainPassword = $plainPassword;
}
/**
* Set fullname
*
* @param string $fullname
*
* @return User
*/
public function setFullname($fullname)
{
$this->fullname = $fullname;
return $this;
}
/**
* Get fullname
*
* @return string
*/
public function getFullname()
{
return $this->fullname;
}
/**
* Set createdat
*
* @param \DateTime $createdat
*
* @return User
*/
public function setCreatedat($createdat)
{
$this->createdat = $createdat;
return $this;
}
/**
* Get createdat
*
* @return \DateTime
*/
public function getCreatedat()
{
return $this->createdat;
}
/**
* Set modifiedat
*
* @param \DateTime $modifiedat
*
* @return User
*/
public function setModifiedat($modifiedat)
{
$this->modifiedat = $modifiedat;
return $this;
}
/**
* Get modifiedat
*
* @return \DateTime
*/
public function getModifiedat()
{
return $this->modifiedat;
}
/**
* The __toString method allows a class to decide how it will react when it is converted to a string.
*
* @return string
* @link http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.tostring
*/
function __toString()
{
return "id: ". $this->id ." email: ". $this->username . " fullname: ". $this->fullname . " isactive: ". $this->isactive .
" createdat: ". $this->createdat->format('Y-m-d H:i:s') ." updatedat: ". $this->modifiedat->format('Y-m-d H:i:s');
}
}
这是我的单元测试classes:
TestBase.class
namespace tests\AppBundle\Controller;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\DependencyInjection\Container;
use Doctrine\Common\Annotations\AnnotationRegistry;
use AppKernel;
AnnotationRegistry::registerFile("../../../vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php");
require_once __DIR__ . "/../../../vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/AnnotationDriver.php";
class TestBase extends \PHPUnit_Framework_TestCase
{
/**
* @var Application
*/
protected $application;
/**
* @var \Doctrine\ORM\EntityManager
*/
protected $entityManager;
/**
* @var \AppKernel
*/
protected $kernel;
/**
* @var Container
*/
protected $container;
protected function setUp()
{
$this->kernel = new AppKernel("test", true);
$this->kernel->boot();
$this->application = new Application($this->kernel);
$this->application->setAutoExit(false);
// Store the container and the entity manager in test case properties
$this->container = $this->kernel->getContainer();
$this->entityManager = $this->container->get("doctrine")->getManager();
if(is_null($this->entityManager)){
print("upssss entitiy manager is null :(");
}
parent::setUp();
}
public function tearDown()
{
// Shutdown the kernel.
$this->kernel->shutdown();
parent::tearDown();
}
}
我在这里测试我的用户 class 只是打印数据库..
UserTest.class
namespace tests\AppBundle\Controller;
require_once ("TestBase.php");
class UserTest extends TestBase
{
protected function setUp()
{
parent::setUp();
}
public function tearDown()
{
parent::tearDown();
}
//generic method to list the users
public function listUsers($users ){
echo EOL, EOL;
foreach($users as $user){
echo $user, EOL;
}
echo EOL, EOL;
}
public function testListUsers(){
$users = $this->entityManager->getRepository('AppBundle:User')->findAll();
$this->assertGreaterThan(1, count($users));
$this->listUsers($users);
}
}
顺便说一下,当我不使用 @Assert\NotBlank() 时它会起作用 所以从代码的角度来看完全没有问题......我猜它只是关于单元测试时的自动加载..
我真的被那个卡住了 2 周..
好的,我找到了答案..
当我把test改成dev 在 AppKernel 中有效
旧的是这样的:
$this->kernel = new AppKernel("test", true);
解决方案
$this->kernel = new AppKernel("dev", true);
虽然
我没有改变我的AppKernel.phpuse Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Config\Loader\LoaderInterface;
define('EOL',(PHP_SAPI == 'cli') ? PHP_EOL : '<br />');
class AppKernel extends Kernel
{
public function registerBundles()
{
$bundles = [
new Liuggio\ExcelBundle\LiuggioExcelBundle(),
new Symfony\Bundle\FrameworkBundle\FrameworkBundle(),
new Symfony\Bundle\SecurityBundle\SecurityBundle(),
new Symfony\Bundle\TwigBundle\TwigBundle(),
new Symfony\Bundle\MonologBundle\MonologBundle(),
new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(),
new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(),
new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(),
new AppBundle\AppBundle(),
];
if (in_array($this->getEnvironment(), ['dev', 'test'], true)) {
$bundles[] = new Symfony\Bundle\DebugBundle\DebugBundle();
$bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle();
$bundles[] = new Sensio\Bundle\DistributionBundle\SensioDistributionBundle();
$bundles[] = new Sensio\Bundle\GeneratorBundle\SensioGeneratorBundle();
}
return $bundles;
}
public function getRootDir()
{
return __DIR__;
}
public function getCacheDir()
{
return dirname(__DIR__).'/var/cache/'.$this->getEnvironment();
}
public function getLogDir()
{
return dirname(__DIR__).'/var/logs';
}
public function registerContainerConfiguration(LoaderInterface $loader)
{
$loader->load($this->getRootDir().'/config/config_'.$this->getEnvironment().'.yml');
}
}