Reputation: 61
I'm working on adding some Capybara/RSpec tests for my app and I'm having some issues with one for the create method of a controller.
This is my test:
require 'rails_helper'
RSpec.describe Api::V1::CampgroundsController, type: :controller do
let(:campground_data) { FactoryBot.create :campground_1 }
let(:user) { FactoryBot.create :user_2 }
describe 'POST#create' do
it "admin should be able to create new campgrounds" do
sign_in user
before_count = Campground.count
post :create, params: campground_data, format: JSON
after_count = Campground.count
expect(after_count).to eq(before_count + 1)
end
end
end
Campground Controller - Create Method:
def create
binding.pry
campground = Campground.new(campground_params)
if campground.save
render json: campground
else
render json: { errors: campground.errors.full_messages }
end
end
Strong Params:
def campground_params
params.require(:campground).permit([:name, :caption, :description, :location, :zip_code, :campground_link, :dogs_allowed, :electric_hookups, :water_hookups, :potable_water, :dump_station, :bathrooms, :showers])
end
When I run the test it fails on this line: post :create, params: campground_data, format: JSON
. The error it kicks back is undefined method
symbolize_keys' for #Campground:0x00007f9887ca4910`
I've been stuck on this problem for a stupid amount of time and after hours of googling, scouring the documentation, and looking through old posts I'm still unsure what the problem. The create method works in production but I can't figure out what I need to do to get this to work in RSpec. I'm assuming I'm doing something wrong about how I'm passing in the data but I'm not sure how else to do it. I did try creating the campground with FactoryBot and then doing this:
campground = {
name: campground.name,
caption: campground.caption,
description: campground.description,
location: campground.location,
zip_code: campground.zip_code,
campground_link: campground.campground_link,
dogs_allowed: campground.dogs_allowed,
electric_hookups: campground.electric_hookups,
water_hookups: campground.water_hookups,
potable_water: campground.potable_water,
dump_station: campground.dump_station,
bathrooms: campground.bathrooms,
showers: campground.showers }
I no longer get the symbolize_keys
error when I do it this way and I make to the create
method on the controller but when it gets to this line campground = Campground.new(campground_params)
it errors out with the error: ActionController::ParameterMissing: param is missing or the value is empty: campground
I mostly tried it this way as a test and I don't think it's the right way to create the data to pass to the controller anyway. I feel like my first approach should work and is the cleaner way of doing it...I just can't figure out what I'm doing wrong.
Upvotes: 0
Views: 969
Reputation: 106782
let(:campground_data) { FactoryBot.create :campground_1 }
already creates a Campground
in the database and returns the new instance. You get the error message undefined method 'symbolize_keys' for #Campground:0x00007f9887ca4910
because the test expects the argument passed in as params
to be a hash.
Instead of FactoryBot.create
you could use FactoryBot.attributes_for
which does not create an instance in the database but returns a hash containing all the attributes that can be used to create such a record.
I would write the spec like this:
let(:campground_attrs) { FactoryBot.attributes_for :campground_1 }
let(:user) { FactoryBot.create :user_2 }
describe 'POST#create' do
it "admin should be able to create new campgrounds" do
sign_in user
expect {
post :create, params: { campground: campground_attrs }, format: JSON
}.to change { Campground.count }.by(1)
end
end
Upvotes: 1
Reputation: 61
Fixed it by creating the data like this:
let!(:campground_data) { { campground: {
name: "Forked Lake Campground",
caption: "Rustic and remote campground. Almost all sites directly on lake. Many boat-in only.",
description: "Nice campground",
location: "New York",
zip_code: "12847",
campground_link: "https://www.dec.ny.gov/outdoor/24467.html",
dogs_allowed: true,
electric_hookups: false,
water_hookups: false,
potable_water: true,
dump_station: false,
bathrooms: true,
showers: false
} } }
Which mostly makes sense to me although I don't really know how to explain it in a way that would make sense to others.
Upvotes: 0