All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twitter.finatra.test.MockApp.scala Maven / Gradle / Ivy

The newest version!
/**
 * Copyright (C) 2012 Twitter Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.twitter.finatra.test

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import com.twitter.finagle.Service
import com.twitter.finagle.http.Response
import com.twitter.finagle.http.{Request => FinagleRequest, Response => FinagleResponse}
import com.twitter.finatra._
import com.twitter.util.{Await, Future}
import java.net.URLEncoder
import java.util
import org.jboss.netty.buffer.ChannelBuffers
import org.jboss.netty.handler.codec.http.HttpMethod
import org.jboss.netty.util.CharsetUtil._
import scala.collection.JavaConverters._
import scala.collection.Map

class MockApp(service: Service[FinagleRequest, FinagleResponse]) {

  def buildRequest(
    method: HttpMethod,
    path: String,
    params: Map[String, String] = Map(),
    headers: Map[String, String] = Map(),
    body: AnyRef = null
  ): FinagleRequest = {

    // ensure that we don't have both params and body
    if (body != null && !params.isEmpty) {
      throw new RuntimeException("unable to build request.  You can specify EITHER params OR a body, but not BOTH.")
    }

    val request = FinagleRequest(path, params.toList: _*)
    request.httpRequest.setMethod(method)

    // add headers
    headers.foreach {
      header => request.httpRequest.headers().add(header._1, header._2)
    }

    // apply body
    for (buffer <- toByteArray(body)) {
      request.setContent(ChannelBuffers.wrappedBuffer(buffer))
      request.httpRequest.headers().set("Content-Length", buffer.length.toString)
    }

    request
  }

  def execute(
    method: HttpMethod,
    path: String,
    params: Map[String, String] = Map(),
    headers: Map[String, String] = Map(),
    body: AnyRef = null
  ): MockResult = {
    val request = buildRequest(method, path, params, headers, body)
    execute(request)
  }

  def execute(request: FinagleRequest): MockResult = {
    val response: Future[FinagleResponse] = service(request)
    new MockResult(response)
  }

  /**
   * helper method to url encode a value
   */
  private[finatra] def encode(value: AnyRef) = URLEncoder.encode(value.toString, "UTF-8")

  /**
   * encodes a map into a url form-encoded string
   */
  private[finatra] def encodeFormData(params: Map[AnyRef, AnyRef]): String = {
    params.map {
      case (key, value) => encode(key.toString) + "=" + encode(value.toString)
    }.mkString("&")
  }

  /**
   * intelligently convert an AnyRef into a Array[Byte] using the following rules:
   *
   * 
    *
  • value: String => value.getBytes
  • *
  • value: Array[Byte] => value
  • *
  • value: Map[_, _] => url-encoded form data
  • *
  • value: util.Map[_, _] => url-encoded form data
  • *
  • value: AnyRef => uses jackson to attempt to convert this to a json string
  • *
*/ private[finatra] def toByteArray(body: AnyRef): Option[Array[Byte]] = { import MockApp._ val buffer: Array[Byte] = body match { case null => null case value: String => value.getBytes case value: Array[Byte] => value case value: util.Map[_, _] => encodeFormData(value.asInstanceOf[util.Map[AnyRef, AnyRef]].asScala.toMap).getBytes case value: Map[_, _] => encodeFormData(value.asInstanceOf[Map[AnyRef, AnyRef]]).getBytes case anythingElse => mapper.writeValueAsBytes(anythingElse) } Option(buffer) } def get(path: String, params: Map[String, String] = Map(), headers: Map[String, String] = Map(), body: AnyRef = null): MockResult = { execute(HttpMethod.GET, path, params, headers, body) } def post(path: String, params: Map[String, String] = Map(), headers: Map[String, String] = Map(), body: AnyRef = null): MockResult = { execute(HttpMethod.POST, path, params, headers, body) } def put(path: String, params: Map[String, String] = Map(), headers: Map[String, String] = Map(), body: AnyRef = null): MockResult = { execute(HttpMethod.PUT, path, params, headers, body) } def delete(path: String, params: Map[String, String] = Map(), headers: Map[String, String] = Map(), body: AnyRef = null): MockResult = { execute(HttpMethod.DELETE, path, params, headers, body) } def head(path: String, params: Map[String, String] = Map(), headers: Map[String, String] = Map(), body: AnyRef = null): MockResult = { execute(HttpMethod.HEAD, path, params, headers, body) } def patch(path: String, params: Map[String, String] = Map(), headers: Map[String, String] = Map(), body: AnyRef = null): MockResult = { execute(HttpMethod.PATCH, path, params, headers, body) } def options(path: String, params: Map[String, String] = Map(), headers: Map[String, String] = Map(), body: AnyRef = null): MockResult = { execute(HttpMethod.OPTIONS, path, params, headers, body) } def send(request: FinagleRequest) { execute(request) } } object MockApp { val mapper = { val m = new ObjectMapper() m.registerModule(DefaultScalaModule) m } def apply(controller: Controller): MockApp = { val server = new FinatraServer server.register(controller) apply(server) } def apply(server: FinatraServer): MockApp = { val appService = new AppService(server.controllers) val service = server.allFilters(appService) new MockApp(service) } } class MockResult(val response: Future[Response]) { def originalResponse = Await.result(response) def status = originalResponse.getStatus def code = originalResponse.getStatus.getCode def body = originalResponse.getContent.toString(UTF_8) def getHeader(name: String) = originalResponse.headers.get(name) def getHeaders = originalResponse.headerMap }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy