Unit Testing http4s router websocket endpoints
Asked Answered
P

0

7

The idea is to be able to unit test websocket endpoints on a router service. Any other kind of endpoint is fairly easy to test with a Request, but I can't figure out a way of easily testing websocket responses, as hitting the endpoint with a Request will give you a 501 error since you don't have any corresponding socket to handshake with.

This is the router I'm using

def router(averages: IO[SomeAverages]): HttpRoutes[F] =
    HttpRoutes.of[F] {
        case GET -> Root =>
            val toClient: Stream[F, WebSocketFrame] = {
                Stream
                  .awakeEvery[F](5.seconds)
                  .map(_ => {
                      val avg = averages.unsafeRunSync
                      WebSocketFrame.Text(avg.toString)
                  })
            }
            val fromClient: Pipe[F, WebSocketFrame, Unit] = _.evalMap {
                case WebSocketFrame.Text(t, _) => F.delay(println(t))
                case f => F.delay(println(s"Unknown type: $f"))
            }
            WebSocketBuilder[F].build(toClient, fromClient)
    }

The idea is to get something akin to the below code to work with websockets

val server = Server.initServer[IO]
val router = server.router
val request = Request[IO](Method.GET, uri"/")

val io = router.orNotFound.run(request)

val response = io.unsafeRunSync

// response.status should be 200
// will return 501 if a websocket endpoint

I've tried variations of this such as adding headers like

val request = Request[IO](
    Method.GET,
    uri"/",
    Headers(Header("Connection", "Upgrade"), Header("Upgrade", "websocket")
)

Though any Request will return a 501.

I'm not sure where to go from here, so if anyone has any suggestions I'd be glad to hear. I think it has something to do with creating a websocket client, but I don't know of a way to do that in http4s.

Pontiff answered 18/3, 2020 at 11:35 Comment(2)
Hi! If you want to increase the probability of getting an answer, you should always strive to provide a Minimal, Reproducible Example. That way it's easier for people to get started with the problem you have. You don't have to e.g. write the sbt dependencies, but you should add the full Scala code. This means all the imports, definitions of all the types you're using (e.g. SomeAverages), and so on. So that someone who has an http4s project already set up can easily c/p your code, compile it and reproduce your problem immediately.Johppa
WebSocket connections don't seem to be supported by the http4s client yet: github.com/http4s/http4s/issues/330#issuecomment-335553295Rattlepate

© 2022 - 2024 — McMap. All rights reserved.