Тест WebSocket в PlayFramework
У меня есть приложение WebSocket в приложении Play, и я хочу написать для него тест, но я не мог найти никакого примера, как написать такой тест. Я нашел дискуссию в группе play-framework Google, но в последнее время активности не было.
Итак, есть ли идеи по тестированию WebSocket в тесте Java?
Ответы
Ответ 1
Вы можете получить базовый Iteratee, Enumerator и протестировать их напрямую. Таким образом, вам не нужно использовать браузер. Тебе нужен акка-тесткит, чтобы справиться с асинхронным характером итераций.
A Scala пример:
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)
}
}
}
Ответ 2
Я тестирую код WebSockets с помощью Firefox:
https://github.com/schleichardt/stackoverflow-answers/commit/13d5876791ef409e092e4a097f54247d851e17dc#L8R14
Для Java он похож на замену "HTMLUNIT" на "FIREFOX": http://www.playframework.com/documentation/2.1.x/JavaFunctionalTest
Ответ 3
Chrome предоставляет плагин для проверки службы websocket.
Edit
Таким образом, используя плагин (как показано на рисунке ниже), вы можете предоставить URL-адрес websocket и данные запроса и отправить сообщение в службу. Журнал сообщений показывает сообщение, отправленное с клиента, а также ответ службы.
![enter image description here]()
Ответ 4
Предположим, что у вас есть библиотека 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.end, после чего вы получаете полный список исходящих сообщений из метода outgoing.get.