blackghost
blackghost

Reputation: 703

Expect that a JSON has just a particular set of keys in rspec?

I am testing a JSON API, and right now I do this:

expect(json).to have_key('name')
expect(json).to have_key('age')

How can I make sure that the JSON has just the keys name and age, and no other keys?

Upvotes: 10

Views: 9108

Answers (2)

Arup Rakshit
Arup Rakshit

Reputation: 118261

Use the #contain_exactly matcher:

expect(json.keys).to contain_exactly('name', 'age')

Examples

Number #1

Spec:

describe "Hash" do
  subject { {a: 2, b: 3} }

  it "passes" do
    expect(subject.keys).to contain_exactly(:a, :b)
  end
end

Let's run it :

arup@linux-wzza:~/Ruby> rspec spec/test_spec.rb
.

Finished in 0.00227 seconds (files took 0.13131 seconds to load)
1 example, 0 failures

Number #2

Spec:

describe "Hash" do
  subject { {a: 2, b: 3} }

  it "fails" do
    expect(subject.keys).to contain_exactly(:a)
  end
end

Let's run it:

arup@linux-wzza:~/Ruby> rspec spec/test_spec.rb
F

Failures:

  1) Hash fails
     Failure/Error: expect(subject.keys).to contain_exactly(:a)
       expected collection contained:  [:a]
       actual collection contained:    [:a, :b]
       the extra elements were:        [:b]
     # ./spec/test_spec.rb:7:in `block (2 levels) in <top (required)>'

Finished in 0.00243 seconds (files took 0.13206 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/test_spec.rb:6 # Hash fails

Number #3

Spec:

describe "Hash" do
  subject { {a: 2, b: 3, c: 4} }

  it "fails" do
    expect(subject.keys).to contain_exactly(:a, :b)
  end
end

Let's run it:

arup@linux-wzza:~/Ruby> rspec spec/test_spec.rb
F

Failures:

  1) Hash fails
     Failure/Error: expect(subject.keys).to contain_exactly(:a, :b)
       expected collection contained:  [:a, :b]
       actual collection contained:    [:a, :b, :c]
       the extra elements were:        [:c]
     # ./spec/test_spec.rb:7:in `block (2 levels) in <top (required)>'

Finished in 0.00243 seconds (files took 0.13301 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/test_spec.rb:6 # Hash fails
arup@linux-wzza:~/Ruby>

Number #4

When dealing with JSON keys, the splat operator (*) comes in handy to manage a list of arguments.

Spec:

describe "Hash" do
  subject { {a: 2, b: 3} }
  let(:json_keys) { %w{a b} }

  it "passes" do
    expect(subject.keys).to contain_exactly(*json_keys)
  end
end

Let's run it :

arup@linux-wzza:~/Ruby> rspec spec/test_spec.rb
.

Finished in 0.00227 seconds (files took 0.13131 seconds to load)
1 example, 0 failures

Upvotes: 10

engineersmnky
engineersmnky

Reputation: 29318

Have you tried this:

expect(json.keys.sort).to eq(["age","name"])

Or

expect(json.keys).to match_array(["name","age"])

I am assuming the json object is pre-parsed such as let(:json){JSON.parse(something)}. If so this is now a Hash and #keys will return an Array of the keys so compare that to the expected Array.

If not pre-parsed then

expect(JSON.parse(json).keys).to match_array(["name","age"])

Upvotes: 1

Related Questions