PHPUnit:如何测试返回无效的Doctrine Repository方法?

问题描述

我有一个可用于持久存储用户的Doctrine存储库类,我不想检查实体是否真的持久存在,我只想知道在这种情况下该怎么做:

测试具有返回值的存储库方法很容易。但是在这种情况下,我无事可做,我想覆盖100%的代码,而不制作不安全的代码,这些代码可能会像使用@addToAssertionCount一样破裂。

<?PHP

namespace Domain\Repository;

use DateTime;
use Domain\Entity\User;
use Domain\Repository\Interfaces\UserRepositoryInterface;

class UserRepository extends Repository implements UserRepositoryInterface
{
    public function create(User $user): void
    {
        $user->setCreatedAt(new DateTime('Now'));

        $this->getEntityManager()->persist($user);
    }
}

还有一个测试类:

<?PHP

namespace Domain\Repository;

use Doctrine\ORM\EntityManager;
use Domain\Entity\User;
use PHPUnit\Framework\TestCase;

class UserRepositoryTest extends TestCase
{
    private UserRepository $sut;

    public function setUp(): void
    {
        $entity_manager = $this->createMock(EntityManager::class);
        $this->sut = new UserRepository($entity_manager);
    }

    public function test_assert_create(): void
    {
        $user = $this->createMock(User::class);
        $this->sut->create($user);

        // What to assert??
    }
}

在这一点上,一旦persist()方法返回void(我无法嘲笑),我什至不知道要断言什么。

解决方法

关注100%的代码覆盖率不是一个好主意,它鼓励编写几乎没有价值的测试。这意味着什么? create方法有两个副作用:它更改了用户创建日期并将其保留。您可以像这样测试它:

final class UserRepositoryTest extends TestCase
{
    /**
     * @var EntityManager&MockObject
     */
    private EntityManager $entityManager;

    private UserRepository $sut;

    public function setUp(): void
    {
        $this->entityManager = $this->createMock(EntityManager::class);
        $this->sut           = new UserRepository($this->entityManager);
    }

    public function test_create_should_persist_entity(): void
    {
        $user = new User();
        $user->setCreatedAt(new DateTime('2000-01-01 12:15:30'));

        // validate that persist call was made
        $this->entityManager->expects(self::once())
            ->method('persist')
            ->with($user);

        $this->sut->create($user);

        // validate that creation date was set
        self::assertEqualsWithDelta(new DateTime('now'),$user->getCreatedAt(),3);
    }
}

您甚至可以更进一步,并使用回调约束来验证是否在创建持久调用之前设置了创建日期。但是,然后,您将在测试中逐行检查实现。这样一来,人们的测试就会一直中断。

那么,该怎么办呢?关注用户存储库的目的:如果放入某些内容,则应该可以将其取出。但是,这要求您使用实际的实体管理器。但是您写道,您不想检查该实体是否确实存在。在那种情况下,我宁愿不写任何测试,而不是上面给出的示例。