我的 Play 应用程序中有一个 WebSocket,我想为它编写一个测试,但我找不到任何关于如何编写这样一个测试的示例。我发现了一个讨论我在play-framework但最近没有任何活动。
那么,对于如何在 Java 测试中测试 WebSocket 有什么想法吗?
我的 Play 应用程序中有一个 WebSocket,我想为它编写一个测试,但我找不到任何关于如何编写这样一个测试的示例。我发现了一个讨论我在play-framework但最近没有任何活动。
那么,对于如何在 Java 测试中测试 WebSocket 有什么想法吗?
您可以检索底层 Iteratee、Enumerator 并直接对其进行测试。这样你就不需要使用浏览器了。不过,您需要 akka-testkit 来应对迭代的异步特性。
斯卡拉示例:
object WebSocket extends Controller {
def websocket = WebSocket.async[JsValue] { request =>
Future.successful(Iteratee.ignore[JsValue] -> Enumerator.apply[JsValue](Json.obj("type" -> "error")))
}
}
class WebSocketSpec extends PlaySpecification {
"WebSocket" should {
"respond with error packet" in new WithApplication {
val request = FakeRequest()
var message: JsValue = null
val iteratee = Iteratee.foreach[JsValue](chunk => message = chunk)(Akka.system.dispatcher)
Controller.websocket().f(request)(Enumerator.empty[JsValue],iteratee)
TestKit.awaitCond(message == Json.obj("type" -> "error"), 1 second)
}
}
}
我使用 Firefox 测试 WebSockets 代码:
对于 Java,它类似于用 'FIREFOX' 替换 'HTMLUNIT':http ://www.playframework.com/documentation/2.1.x/JavaFunctionalTest
Chrome 提供了一个插件来测试 websocket 服务。
编辑
因此,使用插件(如下图所示),您可以提供 websocket url 和请求数据并将消息发送到服务。消息日志显示从客户端发送的消息以及服务响应。
假设您有一个 websocket 库,它返回控制器使用的 Future[Itearatee[JsValue, Unit], Enumerator[JsValue]]
trait WSLib {
def connect: Future[Itearatee[JsValue, Unit], Enumerator[JsValue]]
}
你想测试这个库。
这是您可以使用的上下文:
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))
}
}
然后你的测试可以写成
"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 的传入消息,然后通过调用incoming.end 关闭连接,然后您从outing.get 方法中获取传出消息的完整列表。