0

I am trying to test to see if posting to a create method in my controller triggers a callback I defined with after_save

Here's the controller method being posted to

def create
@guest = Guest.new(guest_params)
@hotel = Hotel.find(visit_params[:hotel_id])

#set visit local times to UTC
@visit= Visit.new(visit_params)
@visit.checked_out_at = (DateTime.now.utc + visit_params[:checked_out_at].to_i.to_i.days).change(hour: @visit.hotel.checkout_time.hour)
@visit.checked_in_at = Time.now.utc
#@visit.user_id = current_user.id
@self_serve = (params[:self_serve] && params[:self_serve] == "true")
if @guest.save
  @visit.guest_id = @guest.id
  if @visit.save
    if @self_serve
      flash[:notice] = "#{@visit.guest.name}, you have successfully checked in!."
      redirect_to guest_checkin_hotel_path(@visit.hotel)
    else
      flash[:notice] = "You have successfully checked in #{@visit.guest.name}."
      redirect_to hotel_path(@visit.hotel)
    end
  else
    render "new"
  end
else
  render "new"
end
end

Here's my spec/controllers/guests_controller_spec.rb test that is failing

RSpec.describe GuestsController, :type => :controller do
describe "#create" do
    let!(:params) do { name: "John Smith", mobile_number: "9095551234" } end
    context "when new guest is saved" do
        it "triggers create_check_in_messages callback" do
            post :create, params
            expect(response).to receive(:create_check_in_messages)
        end
    end
end
end

Here is my models/concerns/visit_message.rb callback file

module VisitMessage
  extend ActiveSupport::Concern

  included do
    after_save :create_check_in_messages
  end

  def create_check_in_messages
   . . .
  end
end

Here is the fail message when I run 'rspec spec/controllers/guests_controller_spec.rb'

1) GuestsController#create when new guest is saved triggers create_check_in_messages callback
 Failure/Error: post :create, params
 ActionController::ParameterMissing:
   param is missing or the value is empty: guest
 # ./app/controllers/guests_controller.rb:63:in `guest_params'
 # ./app/controllers/guests_controller.rb:10:in `create'
 # ./spec/controllers/guests_controller_spec.rb:36:in `block (4 levels) in <top (required)>'

I've been searching all over stackoverflow with no luck. I appreciate any help!

Nam Nguyen
  • 51
  • 7

1 Answers1

1

I am assuming that the guest_params method in the controller looks something like this:

def guest_params
    params.require(:guest).permit(....)
end

If that is the case, you need to update the POST call in your test case thusly:

post :create, {guest: params}

On a side note, your controller is unnecessarily bloated. I would read up on working with associated models to streamline your code, specifically, using accepts_nested_attributes_for:

http://guides.rubyonrails.org/association_basics.html#detailed-association-reference http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

tagCincy
  • 1,589
  • 10
  • 20
  • Your assumption is correct and I've made that tweak. Thanks! However, it is still failing for me. Is 'expect(response).to receive(:create_check_in_messages)' the correct syntax to test that a callback is being triggered? – Nam Nguyen Dec 19 '14 at 20:59
  • Well, first off, you should be testing this on the ModelSpec, not the ControllerSpec as it is a Model specific action, so that could be the problem. I believe `receive` is the correct evaluator, but in honesty, I normally test callbacks by checking to see if the data manipulation process actually happens. Also, just FYI, you do realize that by using `after_save`, that callback is gonna fire on creates and updates? – tagCincy Dec 19 '14 at 21:27
  • Thanks for pointing those flaws out. I'll make the adjustments and try the data manipulation route. – Nam Nguyen Dec 19 '14 at 22:01