Unable to create a model in Rspec via Post - ruby-on-rails

I'm trying to create a User in Rspec:
require "rails_helper"
RSpec.describe UsersController, type: :controller do
describe "POST #index" do
it 'should create a user' do
post :create, {name: "name1", age: 25}.to_json, format: :json
# .............
But instead I get validation errors each time: name can't be blank, age can't be blank
The UserController accepts json:
def create
#user = User.new(params1)
if #user.save
render json: #user
else
render json: #user.errors, status: :unprocessable_entity
end
end
def params1
params.permit(:id, :name, :age)
end

The parameters sent to create shouldn't be a json String but a Hash.
From the rspec documentation :
require "rails_helper"
RSpec.describe WidgetsController, :type => :controller do
describe "responds to" do
it "responds to custom formats when provided in the params" do
post :create, { :widget => { :name => "Any Name" }, :format => :json }
expect(response.content_type).to eq "application/json"
end
end
end
So your test should be :
require "rails_helper"
RSpec.describe UsersController, type: :controller do
describe "POST #create" do
it 'should create a user' do
post :create, { user: {name: "name1", age: 25}, :format => :json }
...

Related

Rails API RSpec Test

I'm new to rails api rspec and somehow I cannot make the test work. Can someone provide some inputs in the tests? The models and controllers are more like a pseudocode. I appreciate it. Thank you.
# routes.rb
Rails.application.routes.draw do
resources :users, :only [:create]
end
# app/model/user.rb
class User < ApplicationRecord
validates_uniqueness_of :name
end
# app/controllers/users_controller.rb
def create
#user = User.new(user_params)
if #user.save
head 200
else
render json: { error: 'Failed', status: 400}, status: 400
end
end
def user_params
params.require(:user).permit(:name)
end
# RSpec Test
require 'rails_helper'
RSpec.describe UsersController do
describe '#create' do
context 'the parameter "user[name]"" is blank' do
it 'creates new user' do
#Test Here
end
it 'renders empty response' do
#Test Here
end
it 'renders response with status 200' do
#Test Here
end
end
end
end
spec/models/user_spec.rb make sure you install gem shoulda-matchers and factory_bot_rails
require 'rails_helper'
RSpec.describe User, type: :model do
let(:user) { create(:user) }
describe "validation" do
it { should validate_uniqueness_of(:name) }
end
end
spec/controllers/users_controller_spec.rb
require 'rails_helper'
RSpec.describe UserssController, type: :controller do
describe "POST /users" do
it "when create user successfully return status 200" do
post :create, params: { name: "name" }
expect(response.status).to eq 200
end
it "when create user errors return status 400" do
post :create, params: { name: "name duplicate" }
expect(response.status).to eq 400
end
end
end
I hope it helps for you

I am getting error while running the rspec test case for API results at particular subdomain

I am getting
bad argument (expected URI object or URI string)
error while running the below code at line
get :show, id: owner.id, format: :json, subdomain: 'api'
describe Api::V1::OwnersController, :type => :controller do
render_views
#before { host! "api.localhost:3000" }
let(:owner) {FactoryGirl.create(:owner)}
before(:each) do
request.host = "api.localhost:3000"
end
describe "GET #show" do
it "returns the information about an Owner on a hash" do
# TODO get this working
get :show, id: owner.id, format: :json, subdomain: 'api'
expect(response.status).to eq(200)
#owner_response = JSON.parse(response.body, symbolize_names: true)
#expect(owner_response[:email]).to eql #owner.email
end
end
end
I am adding a subdomain to render the API results here.
Try this:
get :show, params: { id: owner.id, format: :json, subdomain: 'api' }

Rspec tests failing with unexpected message :articles

I'm using Devise with Rspec. So I've two model called User and Article which is article belongs_to the user
When run rspec, i got an error which is say:
1) ArticlesController POST #create with valid attributes saves the article
Failure/Error: post :create, { article: valid_attributes }
#<Double "user"> received unexpected message :articles with (no args)
# ./app/controllers/articles_controller.rb:17:in `create'
# ./spec/controllers/articles_controller_spec.rb:43:in `block (4 levels) in <top (required)>'
Below is my articles_controller.rb
def new
#article ||= Article.new
render
end
def create
#article = #user.articles.new(article_params)
if #article.save
redirect_to articles_path, notice: "Well done brah! Your article has been publish"
else
render 'new'
end
end
spec/controllers/articles_controller_spec.rb
RSpec.describe ArticlesController, type: :controller do
let(:article) { FactoryGirl.create(:article) }
let (:valid_attributes) { FactoryGirl.attributes_for(:article) }
describe "POST #create" do
context "with valid attributes" do
it "saves the article" do
sign_in
post :create, { article: valid_attributes }
expect(Article.count).to eq(1)
end
end
end
spec/factories/articles.rb
FactoryGirl.define do
factory :article do
title "Article Title"
content "Article Content"
default_image "default_image"
user
category
end
end
Where is my mistake? I stuck here
UPDATED
spec/rails_helper.rb
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
config.include ControllerHelpers, :type => :controller
end
spec/support/controller_helpers.rb
module ControllerHelpers
def sign_in(user = double('user'))
if user.nil?
allow(request.env['warden']).to receive(:authenticate!).and_throw(:warden, {:scope => :user})
allow(controller).to receive(:current_user).and_return(nil)
else
allow(request.env['warden']).to receive(:authenticate!).and_return(user)
allow(controller).to receive(:current_user).and_return(user)
end
end
end
Both of the updated file above i got it from DEvise wiki - https://github.com/plataformatec/devise/wiki/How-To:-Stub-authentication-in-controller-specs
You need to use an actual database record for your user*.
RSpec.describe ArticlesController, type: :controller do
let(:article) { FactoryGirl.create(:article) }
let(:valid_attributes) { FactoryGirl.attributes_for(:article) }
let(:user) { FactoryGirl.create(:user) }
let(:valid_session) { sign_in(user) }
describe "POST #create" do
before { valid_session }
context "with valid attributes" do
it "saves the article" do
# less prone to false positives
expect do
post :create, { article: valid_attributes }
end.to change(Article, :count).by(1)
end
end
end
end
We use expect {}.to change since you can get a false positive if the database is not cleaned out properly.
Devise::TestHelpers already has a sign_in function. So get rid of your ControllerHelpers module so that your project is not linked to the Devise or Warden internals.

Empty response when rendering RABL template with RSPEC

I'm having a perplexing problem where my controller is working fine. However, when I'm testing it with RSPEC it's returning an empty string as the response body.
Here is the controller:
class Api::UsersController < Api::ApplicationController
def show
#user = User.find(params[:id])
render 'show', status: 200
# render json: #user
end
end
And the RABL template I'm rendering:
object #user
attributes :id, :name, :email, :phone_number, :invite_token
Finally here is my spec:
require "spec_helper"
describe Api::UsersController do
it "returns user attributes" do
user = FactoryGirl.create(:user, name: "Mark", email: "foo#bar.com")
get :show, id: user.id
expect(response.status).to eq(200)
output = JSON.parse(response.body)
end
end
When I use render 'show' to render the RABL template my test fails as the response.body is an empty string. However, if I CURL to that endpoint, the body returns just fine.
When I change the controller to: render json: #user the test passes.
Can anyone tell me what's going on here?
Thanks in advance!
try to add render_views at the top of the tests
describe Api::UsersController do
render_views
it "returns user attributes" do
user = FactoryGirl.create(:user, name: "Mark", email: "foo#bar.com")
get :show, id: user.id
output = JSON.parse(response.body)
expect(response.status).to eq(200)
expect(output).to eq(expected_hash)
end
end
Possible reason: RSpec do not render views by default to speed up tests.

RSpec + FactoryGirl and controller specs

I'm trying to add FactoryGirl support the default scaffolded specs in my controllers and I can't seem to find the correct syntax.
Here's an example test:
describe "POST create" do
describe "with valid params" do
it "creates a new Course" do
expect {
post :create, {:course => valid_attributes}, valid_session
}.to change(Course, :count).by(1)
end
do
Which I replace by:
describe "POST create" do
describe "with valid params" do
it "creates a new Course" do
expect {
post :create, course: FactoryGirl.build(:course)
}.to change(Course, :count).by(1)
end
do
spec/factories/courses.rb
FactoryGirl.define do
factory :course do
association :provider
name "Course name"
description "course description"
end
end
app/models/course.rb
class Course < ActiveRecord::Base
validates :name, :presence => true
validates :description, :presence => true
validates :provider_id, :presence => true
has_many :terms
belongs_to :provider
end
app/controllers/courses_controller.rb
# POST /courses
# POST /courses.json
def create
#course = Course.new(course_params)
respond_to do |format|
if #course.save
format.html { redirect_to #course, notice: 'Course was successfully created.' }
format.json { render action: 'show', status: :created, location: #course }
else
format.html { render action: 'new' }
format.json { render json: #course.errors, status: :unprocessable_entity }
end
end
end
It usually fails with: "ActionController::ParameterMissing: param not found: course" does anyone have any idea?
Thanks!
Francis
Try:
describe "POST create" do
describe "with valid params" do
it "creates a new Course" do
expect {
post :create, course: FactoryGirl.attributes_for(:course, provider_id: 1)
}.to change(Course, :count).by(1)
end
end
end
Factory Girl uses attributes_for option to generate a hash of values as opposed to a Ruby object.

Resources