使用ScalaJ-Http时如何进行单元测试?

时间:2017-01-31 17:14:53

标签: scala unit-testing

我希望将ScalaJ-Http用作http客户端。链接:https://github.com/scalaj/scalaj-http

我如何在单元测试中模拟HttpHttpRequest一个具有一行代码的类val response: HttpResponse[String] = Http("http://foo.com/search").param("q","monkeys").asString

该类将从方法调用参数中获取url和params。所以我不能注入HttpRequest

2 个答案:

答案 0 :(得分:1)

我所做的是创建一个ScalajHttp包装类,如下所示:

import scalaj.http.{Http, HttpRequest}

/**
  * This wraps the Scalaj Http object so it can be injected.
  */
class ScalajHttp {

  def url(url: String): HttpRequest = Http(url)

}

然后你可以轻松地将它注入另一个类:

class Foo(http: ScalajHttp) {

  def doBar() = {
     val response = http.url("http://...").asString
  } 

}

然后,对于模拟,你可以使用像Specs2这样的东西并创建ScalajHttp的模拟。

答案 1 :(得分:0)

好奇,如果你已经有了解决方案。我遇到了同样的问题。

我现在终于通过创建一个虚拟服务'来解决它。在测试中使用Scalatra / Jetty并在那里指定预期的响应。所以,它不是真的嘲笑,但它会为我做。

这种方法的缺点是你必须包括Scalatra,Jetty-server和Jetty-servlet作为额外的依赖项(可选择使用scope = test)。

def mockService: Server = {
  class MockedServlet extends ScalatraServlet {

    get("/") {
      // fill in whatever you expect here
      Ok("I'm alive!")
    }
  }

  class ServletMounter extends LifeCycle {
    override def init(context: ServletContext): Unit = {
      context.mount(new MockedServlet, "/mock")
    }
  }

  new Server(20002) {
    val servlet = new ServletContextHandler(ServletContextHandler.NO_SESSIONS) {
      addEventListener(new ScalatraListener() {
        override def probeForCycleClass(classLoader: ClassLoader): (String, LifeCycle) = {
          (classOf[ServletMounter].getSimpleName, new ServletMounter)
        }
      })
    }
    setHandler(servlet)
  }
}

private val server = mockService

override protected def beforeAll(): Unit = {
  super.beforeAll()
  server.start()
}

override protected def afterAll(): Unit = {
  server.stop()
  server.destroy()
  super.afterAll()
}

// a simple test
"service up" should "return a 200 when the mocked service is up" in {
  val response = Http("http://localhost:20002/mock/").asString
  response.code shouldBe 200
  response.body shouldBe "I'm alive!"
}

编辑2017年3月2日: 经过一些考虑之后,我改变了我的代码,以便通过scalaj-http在' facade'中进行HTTP调用。特质,我可以在我的测试中嘲笑。现在,我不是做实际的HTTP请求,而是模拟外观并发回预期的HTTPResponse。与上面显示的解决方案相比,这更加清晰,上面提到的依赖性不再是必需的,并且设置更容易。外立面可以注入'进入作为构造函数参数或自我类型注释进行HTTP调用的类。