简体   繁体   中英

Not getting the exact output when testing Create action in RSpec

I am doing my testing with mocks and stubs but I can't get the desired output I want when testing the create action in the controller.

The failing test:

describe 'authenticated user' do
  let(:user) { instance_double(User) }
  before do
    allow(controller).to receive(:current_user) { user }
    allow(controller).to receive(:authenticate_user!) { true }
  end

  describe "POST create" do
    let(:achievement_params) { { title: "title" } }
    let(:create_achievement) { instance_double(CreateAchievement) }

    before do
      allow(CreateAchievement).to receive(:new) { create_achievement }
    end

    it 'sends create message to CreateAchievement' do
    expect(CreateAchievement).to receive(:new).with(achievement_params, user)
    expect(create_achievement).to receive(:create)
    post :create, achievement: achievement_params

    end
  end
end

The create action in the controller

def create
  service = CreateAchievement.new(params[:achievement], current_user)
  service.create
  render nothing: true
end

The error:

  1) AchievementsController authenticated user POST create sends create message to CreateAchivement
 Failure/Error: expect(CreateAchievement).to receive(:new).with(achievement_params, user)

   #<CreateAchievement (class)> received :new with unexpected arguments
     expected: ({:title=>"title"}, #<InstanceDouble(User) (anonymous)>)
          got: (<ActionController::Parameters {"title"=>"title"} permitted: false>, #<InstanceDouble(User) (anonymous)>)
   Diff:
   @@ -1,2 +1,3 @@
   -[{:title=>"title"}, #<InstanceDouble(User) (anonymous)>]
   +[<ActionController::Parameters {"title"=>"title"} permitted: false>,
   + #<InstanceDouble(User) (anonymous)>]

that's because you need to "permit" your POST values, in your controller:

def achievement_params
  params.require(:achievement).permit(:title)
end

and then, call it from your controller action:

service = CreateAchievement.new(achievement_params, current_user)

You need to permit the parameters in your controller:

private

def achievement_params
   params.require(:achievement).permit(:title)
end

Change your create method to receive theses params, instead of params[:achievement] :

def create
  service = CreateAchievement.new(achievement_params, current_user)
  service.create
  render body: nil
end

And in your spec, you need to create the params using the ActionController::Parameters.new method permitting the title param:

let(:achievement_params) { ActionController::Parameters.new('title': 'title').permit(:title) }

Like the following:

describe 'POST create' do
  let(:achievement_params) { ActionController::Parameters.new('title': 'title').permit(:title) }
  let(:create_achievement) {instance_double(CreateAchievement)}

  before do
    allow(CreateAchievement).to receive(:new) {create_achievement}
  end

  it 'sends create message to CreateAchievement' do
    expect(CreateAchievement).to receive(:new).with(achievement_params, user)
    expect(create_achievement).to receive(:create)

    post :create, params: {achievement: achievement_params }
  end
end

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