簡體   English   中英

我不知道如何用 PHPUnit 測試 Ratchet/Sockets

[英]I can't figure out how to PHPUnit test Ratchet/Sockets

首先承認,我絕對是TDD和單元測試領域的新手。 目前,我正在學習使用 TDD 來提升自己的職業生涯。

我正在重新編程我一年前使用 TDD 編寫的程序。 程序沒有那么復雜。 它監聽一個websocket(Ratchet),接收信息,解析信息,並通過消息總線(RabbitMQ)發送消息。

我試圖通過 TDD 來解決這個問題,所以我開始首先編寫我的測試。

我的監聽器類有 4 個方法。

  • 連接(通過 Ratchet 連接到流)
  • (開始聽)
  • 解析(解析接收到的信息)
  • SendMessage (向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測試的MessageProcessor 它的所有依賴項都是您擁有的類型,因此您可以使用模擬、存根或假實現來測試它們的交互。 此實現過於簡化,並且遺漏了諸如錯誤處理之類的內容,這些內容是您當然想要做的並且當然想要測試的。

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
);

為了確保所有部分協同工作,您可以創建一些端到端測試來執行完整的往返並驗證結果。 首先創建這些測試,允許你做雙循環 TDD

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM