Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/291.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 我能';t弄清楚如何测试棘轮/套筒_Php_Testing_Phpunit_Tdd_Ratchet - Fatal编程技术网

Php 我能';t弄清楚如何测试棘轮/套筒

Php 我能';t弄清楚如何测试棘轮/套筒,php,testing,phpunit,tdd,ratchet,Php,Testing,Phpunit,Tdd,Ratchet,首先让我承认,我绝对是TDD和单元测试领域的新手。目前,我正在学习与TDD合作,以提升我的职业生涯 我正在用TDD重新编程一年前我写的一个程序。程序没有那么复杂。它侦听websocket(Ratchet),接收信息,解析信息,并通过消息总线(RabbitMQ)发送消息 我试图通过TDD来实现这一点,所以我开始先编写测试 我的listener类有4个方法 连接(通过棘轮连接到流) 收听(开始收听) 解析(解析接收到的信息) 发送消息(向RabbitMQ总线发送消息) 我在第一次编写测试时遇到的

首先让我承认,我绝对是TDD和单元测试领域的新手。目前,我正在学习与TDD合作,以提升我的职业生涯

我正在用TDD重新编程一年前我写的一个程序。程序没有那么复杂。它侦听websocket(Ratchet),接收信息,解析信息,并通过消息总线(RabbitMQ)发送消息

我试图通过TDD来实现这一点,所以我开始先编写测试

我的listener类有4个方法

  • 连接(通过棘轮连接到流)
  • 收听(开始收听)
  • 解析(解析接收到的信息)
  • 发送消息(向RabbitMQ总线发送消息)
我在第一次编写测试时遇到的问题

  • 如何模拟棘轮连接并断言我的函数可以“连接”
  • 我如何断言收到的信息符合我的期望

我发现很难找到关于这个特定主题的信息,我知道我的问题很广泛。我不希望有一个完整的解决方案或答案,但希望有进一步研究这一主题的术语,以及关于为这类方法编写测试的讲座/教程。

如果没有看到任何代码,很难争辩。根据你的描述,听起来你有一个类可以做所有的事情。这可能已经是一个让测试变得更加困难的原因

说到单元测试,我喜欢坚持Michael Feathers的定义:

在以下情况下,测试不是单元测试:

  • 它与数据库通信
  • 它通过网络进行通信
  • 它涉及到文件系统
  • 它不能与任何其他单元测试同时运行
  • 您必须对您的环境执行特殊操作(例如编辑配置文件)才能运行它
模拟Ratchet和RabbitMQ连接似乎是使测试符合上述定义的一种方法,但还有另外一句话:“不要模拟你不拥有的东西”。虽然这不是一条硬性规定,但我认为这是一条很好的指导方针。关于这个话题有很多文章

不过,Ratchet对于服务器和事件循环部分有点特殊。但是它经过了很好的测试,所以你不必这么做。我的建议是:将与Ratchet的集成保持得非常薄,这样就没有多少东西需要测试了,只需跳过测试即可

final class MyRatchetApp implements MessageComponentInterface
{
    private MessageProcessor $processor;

    public function __construct(MessageProcessor $processor)
    {
        $this->processor = $processor;
    }

    public function onMessage(ConnectionInterface $from, $msg)
    {
        $this->processor->handle($msg);
    }
    
    // ...
}
这就给您留下了一个
MessageProcessor
,您可以单独进行测试。它的所有依赖项都是您自己的类型,因此您可以使用mock、stub或伪实现来测试它们的交互。这个实现过于简化,并且遗漏了一些东西,比如您当然想做并且当然想测试的错误处理

final class MessageProcessor
{
    private MessageParser $parser;

    private MessageBroadcaster $broadcaster;

    public function __construct(MessageParser $parser, MessageBroadcaster $broadcaster)
    {
        $this->parser      = $parser;
        $this->broadcaster = $broadcaster;
    }

    public function handle(string $rawMessage): void
    {
        $this->broadcaster->send($this->parser->parse($rawMessage));
    }
}

interface MessageParser
{
    /**
     * @throws BadMessageException
     */
    public function parse(string $message): Message;
}

interface MessageBroadcaster
{
    /**
     * @throws UnsupportedMessageException
     * @throws UnroutableMessageException
     */
    public function send(Message $message): void;
}
创建
MessageParser
的实现应该非常简单,并且易于单元测试。
MessageBroadcaster
的RabbitMQ实现将是集成测试的完美候选

最后,将所有具体实现插入到实际应用程序中

$server = IoServer::factory(
    new MyRatchetApp(
        new MessageProcessor(
            new CommandMessageParser(),
            new RabbitMqMessageBroadcaster()
        )
    ),
    8080
);
为了确保所有部件协同工作,您可以创建一些端到端测试,以执行完整的往返并验证结果。首先创建这些测试,允许您执行以下操作