【问题标题】:Mocking Httpcalls always return NullPointerException模拟 Httpcalls 总是返回 NullPointerException
【发布时间】:2022-01-12 17:32:57
【问题描述】:

我正在尝试模拟 Http 调用以进行单元测试。 为此,我做了以下工作,我创建了一个 RequestMock 案例类:

case class RequestMock() {
  def sendRequest(httpRequest: HttpRequest)(implicit actorSystem: ActorSystem): Future[HttpResponse] = {
    Http().singleRequest(httpRequest)
  }
}

在我的服务中,我编写了以下代码:

case class Service(requestHandler: RequestMock) {
....
for {
  response <- {
        requestHandler.sendRequest(
          HttpRequest(
            method = HttpMethods.GET,
            uri = "http://database:9000"
          )
        )
  } yield {
   response
}

}

对于单元测试,我正在尝试模拟 HttpCalls,为此,我做了以下工作:

def test_2 = mock[RequestMock]

为了定义模拟行为,我做了以下操作

      when(test_2.sendRequest(
        HttpRequest(
          method = HttpMethods.GET,
          uri = "http://database:9000")
      )).thenReturn{
        Future(
          HttpResponse(
            StatusCodes.OK,
            entity = HttpEntity(ContentTypes.`text/plain(UTF-8)`,"connection established"))

但是,当我执行单元测试时,我总是收到以下错误:

java.lang.NullPointerException

有谁知道我该如何解决这个问题?

【问题讨论】:

  • 你从哪里得到异常?你试过调试你的代码吗?
  • 是的,我在 requestHandler.sendRequest 中遇到了错误
  • 能否提供更多的测试线?如何在测试中创建 Service 对象?您是否将模拟的请求传递给Service
  • 我有一个服务类,定义如下:case class Service(requestHandler: RequestMock) { def getDatabase{ for { response &lt;- { requestHandler.sendRequest( HttpRequest( method = HttpMethods.GET, uri = "http://database:9000" ) ) } yield { response } ,我有路由类:case class ServiceRoute(sendRequest: RequestMock) { def getAdWeeksRoute: Route = path("database" ) { get { service.getDatabase } }
  • 对于测试类:``` def httpRequestMock = mock[RequestMock] val databaseRoutes = ServiceRoute(httpRequestMock) private val routes = Route.seal(databaseRoutes .routes) ```

标签: scala unit-testing mocking mockito httprequest


【解决方案1】:

几个问题。 首先,test_2 应该是val,而不是def。 使用 def 就像您拥有它一样,每次访问它时都会获得不同的实例。因此,您在一个实例上定义存根,然后使用另一个实例创建您的Service,该实例没有定义sendRequest,因此默认返回null,这会导致您的NPE

修复此问题后您可能会遇到的下一个问题是您没有定义所有的行为。

when(test_2.sendRequest(
        HttpRequest(
          method = HttpMethods.GET,
          uri = "http://database:9000")
      ))

仅为具有此特定参数值的方法调用创建存根。因此,如果您的测试尝试创建 POST 或访问不同的端点,您将再次获得 NPE。

即使您只使用一个请求,最好为 any 参数定义存根,以避免在代码碰巧发送不同的请求时出现奇怪的 NPE 失败(您正在编写 test,所以不应该只是自动假设代码将始终按照您的预期进行 - 如果是这种情况,您首先不需要测试):

when(test2.sendRequest(any)),thenReturn(Future.successful(...))

(请注意上面的Future.successful - 这是创建立即满足的Future 的正确方法,您正在做的事情使它在线程上运行......在您的情况下不是什么大问题,但仍然很恶心)。

然后,运行测试代码后,您可以检查传递给sendRequest的参数值是否与您期望的一样:

verify(test2)
  .sendRequest(HttpRequest(method = HttpMethods.GET, uri = "http://database:9000"))

【讨论】:

    猜你喜欢
    • 2023-01-28
    • 1970-01-01
    • 1970-01-01
    • 2019-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-18
    • 2014-05-16
    相关资源
    最近更新 更多