使用PHP匿名类测试收集服务
#php #测试 #symfony #phpunit

很多次我们举行的课程,遵循相同的合同纳入收款。一个示例将是一个持有服务的集合,该服务使用不同的渠道向用户发送通知。

在本文中,我们将看到如何使用anonymous classes测试我们从集合中获得正确的服务。

首先,让我们定义我们的持有服务必须实现的接口

interface NotificationHandlerInterface {

    public function send(mixed $data): void;
    public function getName(): string;
}

现在,让我们看看看待我们集合的服务的样子:

  class NotificationHandlerDiscover {

    /**
     * @var NotificationHandlerInterface[]
     */
    private array $collection;

    public function __construct(iterable $collection) {
        $this->collection = $collection;
    }

    public function getHandler(string $name): NotificationHandlerInterface {
        $handlers = array_filter(
            $this->collection, 
            fn(NotificationHandlerInterface $handler) => $handler->getName() === $name
        );
        if(count($handlers) === 0){
            throw new \InvalidArgumentException('There is no service named ' . $name);
        }

        return array_pop($handlers);
    }
}

我们不介意如何在 NotificationHandlerDiscover 中加载集合,因为我们只想测试它可以通过正确的服务来传递 $ name
现在让我们看看测试的样子

class NotificationHandlerDiscoverTest extends TestCase
{
    public function testEmailHandler()
    {
        $notificationHandlerDiscover = new NotificationHandlerDiscover($this->getCollection());
        $emailHandler = $notificationHandlerDiscover->getHandler('email');

        $this->assertInstanceOf(NotificationHandlerInterface::class, $emailHandler);
        $this->assertEquals('email', $emailHandler->getName() );
    }

    public function testSmsHandler()
    {
        $notificationHandlerDiscover = new NotificationHandlerDiscover($this->getCollection());
        $emailHandler = $notificationHandlerDiscover->getHandler('sms');

        $this->assertInstanceOf(NotificationHandlerInterface::class, $emailHandler);
        $this->assertEquals('sms', $emailHandler->getName() );
    }

    public function testUnexistingHandler()
    {
        $this->expectException(\InvalidArgumentException::class);
        $notificationHandlerDiscover = new NotificationHandlerDiscover($this->getCollection());
        $notificationHandlerDiscover->getHandler('telegram');
    }

    /**
     * @return NotificationHandlerInterface[]
     */
    private function getCollection(): array
    {
        $handlerEmail = new class implements NotificationHandlerInterface {

            public function send(mixed $data): void {  }

            public function getName(): string
            {
                return 'email';
            }
        };

        $handlerSms = new class implements NotificationHandlerInterface {

            public function send(mixed $data): void {  }

            public function getName(): string
            {
                return 'sms';
            }
        };

        return [
            $handlerSms,
            $handlerEmail
        ];
    }
}

正如我们在上面看到的,我们也不介意处理程序植入术的工作原理。我们正在测试我们的发现处理程序是否获得正确的服务或在不存在此类服务时会引发预期的异常。

使用匿名类我们可以创建一个“ fly on the Fly”数组,该数组包含两个实现 NotificationHandlerInterface 的类。我们只需要写 getName()方法代码,该代码被发现类使用以找到服务。