Mass Spec

Build Status GitHub releases GitHub license

Web API testing library

Mass Spec prevents HTTP::Server from starting a TCPServer and use IO::Memory instead of TCPSocket for fast testing.

Since Mass Spec works with standard library, it can easily support the frameworks based on HTTP::Server.

Installation

Add this to your application's shard.yml:

development_dependencies:
  mass_spec:
    github: c910335/mass-spec

Usage

require "spec"
require "mass_spec"
include MassSpec::GlobalDSL

server = HTTP::Server.new do |context|
  context.response.content_type = "application/json"
  context.response.print(context.request.body.try &.gets_to_end)
end

server.listen

describe "Server" do
  it "echoes in json" do
    post("/", body: {
      "Khassar de templari!" => "From order comes justice!",
      "Adun Toridas!"        => "Adun hide you",
      "Nahda gahla"          => nil,
    }.to_json)

    status_code.should eq(200)
    headers.should contain({"Content-Type", ["application/json"]})
    body.should eq(%({"Khassar de templari!":"From order comes justice!","Adun Toridas!":"Adun hide you","Nahda gahla":null}))
    json_body.should eq({
      "Khassar de templari!" => "From order comes justice!",
      "Adun Toridas!"        => "Adun hide you",
      "Nahda gahla"          => nil,
    })

    json_body.should contain({
      "Khassar de templari!" => "From order comes justice!",
      "Adun Toridas!"        => String,
    })
    json_body.should match({
      "Khassar de templari!" => String,
      "Adun Toridas!"        => "Adun hide you",
      "Nahda gahla"          => Nil,
    })
  end
end

Making Requests

Mass Spec supports the following HTTP verbs via HTTP::Client, and the usage of them is the same as HTTP::Client.

Handling Responses

After a request, you can access these getters.

Expectations

Besides built-in expectations, Mass Spec also provides contain and match for JSON::Any.

json = JSON.parse(%({"array":[1,2,3],"number":1,"float_number":1.5,"string":"str","null":null,"hash":{"a":1}}))

describe "contain with JSON::Any" do
  it "checks whether json contains the values or types" do
    json.should contain({
      "array"  => Array,
      "number" => 1,
      "hash"   => {"a" => Int64},
    })
  end
end

describe "match with JSON::Any" do
  it "checks whether json matches the values or types" do
    json.should match({
      "array"        => [1, 2, 3],
      "number"       => Int64,
      "float_number" => 1.5,
      "string"       => String,
      "null"         => nil,
      "hash"         => Hash,
    })
  end
end

Configuration

You can specify headers that will be applied to every requests.

MassSpec.configure do
  headers({"Authorization" => "Bearer some_access_token"})
end

Frameworks

Kemal

Kemal doesn't run HTTP::Server#listen when ENV["KEMAL_ENV"] is "test", so you need to set MassSpec.server manually.

Kemal DSL and MassSpec::GlobalDSL have same method names, so you need to use MassSpec.get instead of get without include MassSpec::GlobalDSL, and so do the other verbs and getters.

ENV["KEMAL_ENV"] = "test"
require "spec"
require "mass_spec"
require "kemal"

get "/hello" do
  {hello: "kemal"}.to_json
end

Kemal.run do |config|
  MassSpec.server = config.server.not_nil! # set `MassSpec.server` manually
end

describe "GET /hello" do
  it "says hello to Kemal" do
    MassSpec.get "/hello" # `MassSpec.get` instead of `get`

    MassSpec.json_body.should eq({"hello" => "kemal"}) # `MassSpec.json_body` instead of `json_body`
  end
end

Amber

# src/controllers/hello_controller.cr
class HelloController < Amber::Controller::Base
  def hello
    respond_with { json({"hello" => "amber"}) }
  end
end

# config/routes.cr
Amber::Server.configure do
  routes :web do
    get "/hello", HelloController, :hello
  end
end

# spec/spec_helper.cr
ENV["AMBER_ENV"] = "test"
require "spec"
require "mass_spec"
require "../src/*" # not `require "../config/*"`
include MassSpec::GlobalDSL

# spec/controllers/hello_controller_spec.cr
describe HelloController do
  describe "GET #hello" do
    it "says hello to Amber" do
      get "/hello"

      json_body.should eq({"hello" => "amber"})
    end
  end
end

Contributing

  1. Fork it ( https://github.com/c910335/mass-spec/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors