Rails API: How to properly test that response contains the correct object?

Hello everyone,

This should be a really simple thing, but I’ve spent the last hour or so googling and haven’t found an answer. I’m writing an API for practice, and I want to test that the response of a show action is actually the expected.

The controller:

def show 
  render json: @user, status: :ok
end

The spec:

expect(response.body).to eq(user.to_json)

I’d expect this to pass, but timestamps are formatted different in each part of the expectation, so it fails. So, at the moment, for the test to pass, I’m doing this workaround:

expect(User.find(JSON.parse(response.body)['id'])).to eq(user)

What’d be the correct way to test this? (And, if you know, why do render json: and .to_json format timestamps differently?)

Thank You!

Hi @carlesjove, rather that changing your expectation, I would suggest getting the timestamps matched. You probably just need something along the lines of this, from the Suspenders repo or casting the timestamp to_i.

If it is a different issue, maybe going from the timestamp string .to_time.iso8601

Hope this helps :slight_smile:

1 Like

I use ActiveModel::Serializers or roar whenever I’m building an API and I would definitely recommend checking them out. In my tests I do this:

get "/api/v1/users/#{user.id}"

expect(status).to eq(200)
expect(response_body).to be_json_eql(UserSerializer.new(user).to_json)

Or for roar:

serialized_user = user.extend(Representer::User).to_json
get "/users/#{user.id}"

expect(last_response.status).to eq(200)
expect(last_response.body).to eq(serialized_user)

AMS and Roar both make sure to return an ISO8601 string. Even if you don’t go with any of those gems, I’d make sure that you also do this like @pedromoreira said , it makes it much easier for API clients to handle your dates.

1 Like

@pedromoreira and @Jurre : thank you for your answers. I was just starting with the API and hadn’t considered any serializer, yet. In fact, I built another API previously using AMS since the beginning, and didn’t run into this issue, and hence my surprise. For now, I’ll stick with the time formatting until I decide on the serializing tools.

Hey Jurre! I just want to say that I was curious about this be_json_eql method you were using in your example, and found out it belonged to json_spec gem. I’m using it now and it works perfectly. Thanks!

2 Likes