No commit activity in last 3 years
No release in over 3 years
Provides two matchers (#have_json_content and #have_json_values) to make testing the content of json responses easy.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
 Dependencies

Development

~> 2.2
~> 1.16
~> 10.0

Runtime

~> 3.0
 Project Readme

JsonResponseMatchers

rspec matchers for testing json responses in a rails application.

Dependencies

  • ruby '>= 2.0.0'
  • rspec '>= 3.0'
  • activesupport '>= 4.0.6'

Installation

Add this line to your application's Gemfile:

group :test do
  gem 'json_response_matchers'
end

And then execute:

$ bundle

Usage

  1. include the matchers in your rspec config
# spec/rails_helper.rb
RSpec.configure do |config|
  # you can include it in a general way
  config.include JsonResponseMatchers
  # but it is recommended to include it only for the request
  config.include JsonResponseMatchers, type: :request
  # or the request and controller specs
  config.include JsonResponseMatchers, type: /request|controller/
end
  1. write more concise request specs
# in your request spec examples
# instead of
item = JSON.parse(response.body)['item']
expect(item['name']).to eq 'item-name'
# use the #have_json_content matcher
expect(response).to have_json_content('item-name').at_key :item, :name

# instead of
items = JSON.parse(repsonse.body)['items']
expect(items.map { |item| item['id'] }).to match_array [ 1, 2, 3, 4, 5 ]
# use the #have_json_values matcher
expect(response).to have_json_values(1, 2, 3, 4, 5).for(:id).at_key :items

general rules

The target of the matchers can be a json parsable string or an object with such a string at the method #body (like the test response in rails request tests).

expect('{"item":{"id":1,"name":"item-name"}}').to have_json_content('item-name').at_key :item, :name
# or if `response.body` contains the above json
expect(response).to have_json_content('item-name').at_key :item, :name

The #at_key method is optional and can receive one or more string, symbol or integer keys.

expect('false').to have_json_content(false)

json = '{"items":[{"id":1,"name":"item-1"},{"id":2,"name":"item-2"}]}'
expect(json).to have_json_values(1, 2).for(:id).at_key 'items'
expect(json).to have_json_values(1, 2).for(:id).at_key :items
expect(json).to have_json_content('item-2').at_key :items, 1, 'name'

Both matchers are composable.

expect('{"item":{"id":1},"user":{"name":"user"}}')
  .to have_json_content(1).at_key(:item, :id)
  .and have_json_values('user').at_key(:user, :name)

expect('{"items":[{"id":1},{"id":2}],"page":1}')
  .to have_json_values(1, 2).for(:id).at_key(:item)
  .and have_json_content(1).at_key(:page)

#have_json_content

Checks single values.

  • If expected value is not a hash, it checks equality

    # all pass
    expect('{"string":"string"}').to have_json_content('string').at_key :string
    expect('{"number":123}').to have_json_content(123).at_key :number
    expect('{"boolean":false}').to have_json_content(false).at_key :boolean
    expect('{"array":["a",2]}').to have_json_content([ 'a', 2 ]).at_key :array
    expect('{"null":null}').to have_json_content(nil).at_key :null
  • If expected value is a hash

    • and #with_full_match is specified, it checks equality

    • otherwise it checks inclusion

    • accepts symbol keys

      expect('{"id":1,"name":"i1"}').to have_json_content('id'=>1).with_full_match # fails
      expect('{"id":1,"name":"i1"}').to have_json_content('id'=>1) # passes
      expect('{"id":1,"name":"i1"}').to have_json_content(name: 'i1', id: 1).with_full_match # passes

#have_json_values

Checks arrays. The expected values are passed as a parameter list (*args) to the matcher.

  • the metod #for is required and can take a string or symbol value

    items = [
      { id: 1, name: 'item-1' },
      { id: 2, name: 'item-2' },
      { id: 3, name: 'item-3' }
    ]
    expect(items.to_json).to have_json_values(1, 2, 3).for('id') # passes
    expect(items.to_json).to have_json_values(1, 2, 3).for(:id) # passes
    expect(items.to_json).to have_json_values(*items) # fails with ArgumentError
  • checks order only if #in_strict_order is specified

    expect(items.to_json).to have_json_values(1, 3, 2).for(:id) # passes
    expect(items.to_json).to have_json_values(1, 3, 2).for(:id).in_strict_order # fails

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/SzNagyMisu/json_response_matchers.

License

The gem is available as open source under the terms of the MIT License.