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
 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.