0

I have this api endpoint wot get all the blogs from my database that works id the user pass an api_key. This works correctly and now I'm trying to testing this endpoint.

Routes:

Rails.application.routes.draw do
  get 'blogs', to: 'blogs#index'
end

Blogs controller:

class BlogsController < ApplicationController
  def index
    if params[:api_key]
      user = User.find_by(api_key: params[:api_key])
      if user.present?
        @blogs = Blog.all
        return render json: @blogs, status: :ok   
      end         
    end
    render json: { error: "Unauthorized!" }, status: :bad_request
  end
end

I'm new to rspec and tests in general, I watched a couple videos and tutorials and this is what I have so far:

spec/requests/blogs_spec.rb

require 'rails_helper'

RSpec.describe 'Blogs API', type: :request do
  let!(:blogs) { Blog.limit(10) }

  describe 'GET /blogs' do
    before { get '/blogs' }
    
    it 'returns status code 400' do
      expect(response).to have_http_status(400)
    end

    context 'when the request is valid' do
      before { get '/blogs', params: { api_key: '123123'} }

      it 'returns status code 400' do
        expect(response).to have_http_status(200)
      end
    end
  end
end

I can't seem to make the last test work and I don't know why. My guess is that I'm not passing api_key correctly, but I don't know how

 1) Blogs API GET /blogs when the request is valid returns status code 400
     Failure/Error: expect(response).to have_http_status(200)
       expected the response to have status code 200 but it was 400
     # ./spec/requests/blogs_spec.rb:28:in `block (4 levels) in <top (required)>'
6
  • find_by does not raise an exception and user is not being used at all, so it wouldn't be causing this error. Could you inform your Rails and RSpec version, please? I ran your example here with Rails 5.1 and RSpec 4.1.2 and tests are green. Commented Jul 25, 2021 at 17:50
  • @JoãoFernandes I'm using rails 5.2.6 and RSpec 3.9.1. I also updated the question because I'm using user to see if exits. Commented Jul 25, 2021 at 20:46
  • Is that user present in the test database? How are you setting up your test environment, fixtures, factories? Commented Jul 25, 2021 at 21:04
  • @Eyeslandic uhmm the user with api_key: '123123' is in the general database. I didn't setup anything extra to test...maybe that's what I'm missing. Should I create a test user with that api_key: '123123'? How would I do that? Commented Jul 25, 2021 at 21:12
  • That is quite a big topic, there are a lot of articles about that. Search for "rspec factorybot" to start with Commented Jul 25, 2021 at 22:47

1 Answer 1

4

Ok, so accordingly to your question + comments, I can assume you are running your tests within test environment, but you are expecting to find a User existing in development database.

FactoryBot

You might wanna use FactoryBot to create records for your testing suite.

Add to your Gemfile:

group :development, :test do
  gem 'factory_bot_rails'
end

In rails_helper.rb, add:

RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods
end

Now you should create your User factory. Create a new file spec/factories/user.rb with the following:

FactoryBot.define do
  factory :user do
    api_key { '123123' }
    # You should define every any other required attributes here so record can be created
  end
end

Finally, in your spec file:

    ....

    context 'when the request is valid' do
      before { get '/blogs', params: { api_key: user.api_key} }
      let!(:user) { create(:user) }

      it 'returns status code 200' do
        expect(response).to have_http_status(200)
      end
    end

    ...

Now your test should pass. Notice that in testing database there is no Blog created also, so:

let!(:blogs) { Blog.limit(10) }

Will return an empty array. You will need to create a Blog factory too, and create blogs like:

let!(:blogs) { create_list(:blog, 2) }

Bonus

As soon as you start improving your tests, you may wanna take a look at Faker and Database Cleaner for ActiveRecord

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.