简体   繁体   中英

Unsure how to pass data for Create method RSpec test

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.

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM