Test WebSocket in PlayFramework

前端 未结 4 1774
梦如初夏
梦如初夏 2021-02-20 16:32

I have a WebSocket in my Play application and I want to write a test for it, but I couldn\'t find any example on how to write such a test. I found a discussion in the play-frame

4条回答
  •  感动是毒
    2021-02-20 16:59

    Assume that you have a websocket library that returns the Future[Itearatee[JsValue, Unit], Enumerator[JsValue]] your controller uses

    trait WSLib {
      def connect: Future[Itearatee[JsValue, Unit], Enumerator[JsValue]]
    }
    

    And you wanna test this library.

    Here is a context you can use:

    trait WebSocketContext extends WithApplication {
      val aSecond = FiniteDuration(1, TimeUnit.SECONDS)
    
    
      case class Incoming(iteratee: Iteratee[JsValue, Unit]) {
    
        def feed(message: JsValue) = {
          iteratee.feed(Input.El(message))
        }
    
        def end(wait: Long = 100) = {
          Thread.sleep(wait) //wait until all previous fed messages are handled
          iteratee.feed(Input.EOF)
        }
      }
    
      case class OutGoing(enum: Enumerator[JsValue]) {
        val messages = enum(Iteratee.fold(List[JsValue]()) {
          (l, jsValue) => jsValue :: l
        }).flatMap(_.run)
    
        def get: List[JsValue] = {
          Await.result(messages, aSecond)
        }
      }
    
      def wrapConnection(connection: => Future[Iteratee[JsValue, Unit], Enumerator[JsValue]]): (Incoming, OutGoing) = {
        val (iteratee, enumerator) = Await.result(conn, aSecond)
        (Incoming(iteratee), OutGoing(enumerator))
      }
    
    }
    

    Then your tests can be written as

    "return all subscribers when asked for info" in new WebSocketContext  {
      val (incoming, outgoing) = wrapConnection(myWSLib.connect)
    
      incoming.feed(JsObject("message" => "hello"))
      incoming.end() //this closes the connection
    
    
      val responseMessages = outgoing.get  //you only call this "get" after the connection is closed
      responseMessages.size must equalTo(1)
      responseMessages must contain(JsObject("reply" => "Hey"))
    }
    

    Incoming represent the messages coming from the client side, while the outgoing represents the messages sent from the server. To write test, you first feed in the incoming messages from incoming and then close the connection by calling incoming.end, then you get the complete list of outgoing messages from the outgoing.get method.

提交回复
热议问题