Coder Social home page Coder Social logo

kituratesting's Introduction

Handler testing example for Kitura

This example implements two new testing objects which are influenced by Go's net/httptest package.
Sources/HTTPTest contains two classes:

The intention behind these packages is to enable testing of handlers without the requirement to run through the Router. It gives fast and simple Unit level testing allowing dependencies to be easilly replaced.

Strucuture of Handlers to provide issolation

public class JSONHandlers {
  /**
  * If your handler needs dependencies then use constuctor
  * injection to manage this
  */
  public init(database:MySQL, logger:Log) {
    self.database = database
    self.logger = logger
  }
    /**
     * Handler for getting an application/json response.
     */
    public func getJSON(
      request: RouterRequest, 
      response: RouterResponse, 
      next: @escaping () -> Void) throws {

      // work for function

      }
}

Dependencies can be issolated within the handlers by using constructor injection, by depending on abstraction using protocols, dependencies can be easily stubbed or mocked in the testing phase.

Test setup

Kitura's RouterRequest and RouterResponse have an underlying object which is based on the protocols ServerRequest and ServerResponse, these implement the basic data stuctures for the HTTP request and response. The classes themselfs have no other dependencies and do not need further abstraction for effective testing. If we take a look at the example below we are creating an instance of HTTPTest.Request and HTTPTest.ResponseRecorder and then using this to create an instance of RouterRequest and RouterResponse. The Kitura classes do have protection level on the constructors for certain elements but this can be bypassed on for testing by using the @testable import KituraNet declaration which allows us to bypass this for testing with out the need to change the protection in the underlying class.

public override func setUp() {
  request = Request(path:"/", method:"GET")
  routerRequest = RouterRequest(request: request!)

  response = ResponseRecorder()
  routerResponse = RouterResponse(
    response: response!,
    router: Router(),
    request: routerRequest!)

  handlers = JSONHandlers()
}

Once we have this setup we can then write a unit test like the one below, this test uses the convenience methods on the ResponseRecorder which captures the response which would ordinarily be sent to the servers output into an internal buffer. We can then access this either as a raw object or as JSON enabling us to assert that the response from the handler was as desired.

public func testReturnsJSONWhenValidRequest() throws {
  try handlers?.getJSON(request: routerRequest!, response: routerResponse!) {}
  let json = response!.jsonBody()

  XCTAssertEqual("Kitura", json["framework"], "Expected response body to contain Kitura")
}

This is an incredibly effective testing strategy as not only do these tests run very fast but it allows full code path checking of the handler. For example if authentication fails and we would like to maje sure that the server will return a 401 status, the dependency responsible for authentication could be setup to return a fail state which would allow us to test that the handler flows through the correct path.

The other benefit of separating code in this way is that we can keep the router setup simple and readable by issolating the work into handler classes which are grouped by behaviour.

// JSON Get request
router.get("/json", handler: jsonHandlers.getJSON)

kituratesting's People

Contributors

bdhernand avatar chiahuang avatar craigkj312 avatar dfirsht avatar dleonard00 avatar ianpartridge avatar lluisgerard avatar nicholasjackson avatar rolivieri avatar tfrank64 avatar thesounddefense avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.