Sometimes I come across three separate checks in specs to make sure the hash is OK: there are keys, there are values, values have the right type.
RSpec.describe UserSerializer do
describe "#as_json" do
let(:user) do
build(:user,
first_name: "Bart",
last_name: "Simpson",
tel: "+777123")
end
let(:json) { described_class.new(user).as_json }
it "has keys" do
expect(json).to include(:first_name, :last_name, :tel)
end
it "has types" do
expect(json[:first_name]).to be_kind_of(String)
expect(json[:last_name]).to be_kind_of(String)
expect(json[:tel]).to be_kind_of(String)
end
it "has values" do
expect(json[:first_name]).to eq(user.first_name)
expect(json[:last_name]).to eq(user.last_name)
expect(json[:tel]).to eq(user.tel)
end
end
end
This spec is more confusing than helpful: when you change fields, you have to update three tests; it's hard to immediately understand what the serializer returns.
Better to use include matcher and skip type checks (it's not the responsibility of the test):
RSpec.describe UserSerializer do
describe "#as_json" do
it "includes first name, last name and tel" do
user = build(:user,
first_name: "Bart",
last_name: "Simpson",
tel: "+777123")
json = described_class.new(user).as_json
expect(json).to include(
first_name: "Bart",
last_name: "Simpson",
tel: "+777123"
)
end
end
end
Top comments (4)
What do you think about taking it one step further?
expect(json).to contain_exactly({
first_name: "Bart",
last_name: "Simpson",
tel: "+777123"}
)
Looks awesome. Thanks!
Thanks, Vasily! This helped me to keep my code cleaner. ⭐️