面对问题测试akka http缓存

时间:2019-03-14 06:07:34

标签: scala caching akka-http

我正在使用Akka HTTP缓存来缓存我的结果。但是我面临测试的问题。

class GoogleAnalyticsController @Inject()(cache: Cache[String, HttpResponse],
                                          googleAnalyticsApi: GoogleAnalyticsTrait,
                                          googleAnalyticsHelper: GoogleAnalyticsHelper)
                                         (implicit system: ActorSystem, materializer: ActorMaterializer) {


def routes: Route =

      post {
        pathPrefix("pageviews") {
          path("clients" / Segment) { accountsClientId =>
            entity(as[GoogleAnalyticsMetricsRequest]) { googleAnalyticsMetricsRequest =>
         val googleAnalyticsMetricsKey = "key"
         complete(
           cache.getOrLoad(googleAnalyticsMetricsKey, _ => getGoogleAnalyticsMetricsData(accountsClientId, googleAnalyticsMetricsRequest))
          ) 
         }

       }
     }
   }

 private def getGoogleAnalyticsMetricsData(accountsClientId: String,
                                            request: GoogleAnalyticsMetricsRequest) = {
    val payload = generate(request)
    val response = googleAnalyticsApi.googleAnalyticsMetricResponseHandler(accountsClientId, payload) // response from another microservice
googleAnalyticsHelper.googleAnalyticsMetricResponseHandler(
       googleAnalyticsMetricsRequest.metricName, response)
}

}

class GoogleAnalyticsHelper extends LoggingHelper {

  def googleAnalyticsMetricResponseHandler(metricName: String, response: Either[Throwable, Long]): Future[HttpResponse] =
    response.fold({ error =>
      logger.error(s"An exception has occurred while getting $metricName from behavior service and error is ${error.getMessage}")
      Marshal(FailureResponse(error.getMessage)).to[HttpResponse].map(httpResponse => httpResponse.copy(status = StatusCodes.InternalServerError))
    }, value =>
      Marshal(MetricResponse(metricName, value)).to[HttpResponse].map(httpResponse => httpResponse.copy(status = StatusCodes.OK))
    )

}

测试案例:仅共享相关部分

"get success metric response for " + pageviews + " metric of given accounts client id" in { fixture =>
      import fixture._

      val metricResponse = MetricResponse(pageviews, 1)
      val eventualHttpResponse = Marshal(metricResponse).to[HttpResponse].map(httpResponse => httpResponse.copy(status = StatusCodes.OK))

      when(cache.getOrLoad(anyString, any[String => Future[HttpResponse]].apply)).thenReturn(eventualHttpResponse)
      when(googleAnalyticsApi.getDataFromGoogleAnalytics(accountsClientId, generate(GoogleAnalyticsRequest(startDate, endDate, pageviews))))
        .thenReturn(ApiResult[Long](Some("1"), None))
      when(googleAnalyticsHelper.googleAnalyticsMetricResponseHandler(pageviews, Right(1))).thenReturn(eventualHttpResponse)

      Post(s"/pageviews/clients/$accountsClientId").withEntity(requestEntity) ~>
        googleAnalyticsController.routes ~> check {
        status shouldEqual StatusCodes.OK
        responseAs[String] shouldEqual generate(metricResponse)
      }
    }

这样做,我最好测试缓存是否具有密钥,但不能测试缓存是否未命中。在代码覆盖率中,它缺少以下突出显示的部分

  

cache.getOrLoad(googleAnalyticsMetricsKey, _ =>   getGoogleAnalyticsMetricsData(accountsClientId,   googleAnalyticsMetricsRequest)

如果存在设计问题,请随时指导我如何使我的设计可测试。

谢谢。

1 个答案:

答案 0 :(得分:2)

我认为您不需要模拟缓存。您应该为缓存创建一个实际的对象,而不是模拟对象。

您要做的是,您已模拟了缓存,在这种情况下,当您提供模拟值时,突出显示的部分将不会被调用。在以下存根中,只要找到cache.getOrLoad,就返回eventualHttpResponse

when(cache.getOrLoad(anyString, any[String => Future[HttpResponse]].apply)).thenReturn(eventualHttpResponse)

,因此永远不会调用函数getGoogleAnalyticsMetricsData(accountsClientId, googleAnalyticsMetricsRequest)