skip to Main Content

I have a column that it’s a DateTimeImmutable that save when the user has joined the platform. I’m making the phpunit test and i would like to validate that the colum can’t be updated. I would like to detect the error before arriving to the SQL error (error when trying to update column).

 #[ORMColumn(updatable: false)]
    #[AssertType(
        type: 'object',
        message: 'The value {{ value }} is not a valid {{ type }}.'
    )]
    private ?DateTimeImmutable $joinedAt = null;

I’ve tried to update the entity column and then call the $manager->persist($entity) to see if there is an error at that time, but nothing happen.

  public function testInvalidJoinedAt(): void
    {
        $manager = static::getContainer()->get(EntityManagerInterface::class);

        // User joinedAt cannot be updated
        $now = new DateTimeImmutable();
        $existingUser = $this->getRepository(UserRepository::class)->find(0);
        $existingUser->setJoinedAt($now);

        try {
            $manager->persist($existingUser);
        } catch (Throwable $err) {
            $this->assertEquals('???', $err->getMessage());
        }
    }

An assert type like "#[AssertNotUpdatable]" would be the perfect solution but there isn’t something like that.

2

Answers


  1. You can create your own custom validator checkout the doc here enter link description here
    in your src/Validator/Constraints add the files
    1)

    class fileName extends Constraint
    {
        public $message = 'Error Message Goes here for not modifd property';
    }
    
     class FileName extends ConstraintValidator
     {
         public function validate($value, Constraint $constraint)
         {
             if ($value !== null) {
             $this->context->buildViolation($constraint->message)->addViolation();
         }
       }
     }
    
    1. you can add your custom validator to your entity asserts

      /**
        * @ORMColumn(updatable=false)
        * @customValidatorvalidatorName
        */
       private ?DateTimeImmutable $joinedAt = null;
      
    Login or Signup to reply.
  2. Doctrine does not validate Symfony Validation attributes. You must validate the entity with the Symfony Validator before saving it.

    With a custom validator you need to know if it is an insert or an update, because the Symfony validator does not know if you are doing an insert or an update. Such could create such a custom validator. But it is a bigger effort.

    I would solve it based on your method testInvalidJoinedAt() so you do not have to validate.

    namespace AppEntity;
    
    use DoctrineORMMappingColumn;
    
    class Entity
    {
        #[Column(updatable: false)]
        private ?DateTimeImmutable $joinedAt = null;
    
        public function getJoinedAt(): ?DateTimeImmutable
        {
            return $this->joinedAt;
        }
    
        public function setJoinedAt(?DateTimeImmutable $joinedAt): void
        {
            if (!$this->joinedAt instanceof DateTimeImmutable) {
                $this->joinedAt = $joinedAt;
            }
        }
    }
    

    Example UnitTest

    class EntityTest extends TestCase
    {
        public function testNewEntity() {
            $dateTime = new DateTimeImmutable();
            $entity = new Entity();
            $entity->setJoinedAt($dateTime);
            $this->assertEquals($dateTime, $entity->getJoinedAt());
        }
    
        public function testEntityFromDatabase() {
            // Mock entity from database
            $dateTime = new DateTimeImmutable();
            $dateTime->setDate(2022, 9, 17)->setTime(19, 31, 41);
            $entityFromDatabase = new Entity();
            $entityFromDatabase->setJoinedAt($dateTime);
    
            // Set joinedAt update
            $entityFromDatabase->setJoinedAt(
                (new DateTimeImmutable())->setDate(2023, 10, 19)->setTime(8, 11, 15)
            );
    
            $this->assertEquals($dateTime, $entityFromDatabase->getJoinedAt());
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search