tomekfranek
tomekfranek

Reputation: 7099

How to stub after_create callback save! in model?

I receive following error:

Output:

1) LabelsController#create label is new creates a new label
   Failure/Error: post :create, attributes[:label], format: :json
   NoMethodError:
     undefined method `save!' for nil:NilClass
   # ./app/models/labeling.rb:17:in `update_target'

In Labeling model:

after_create :update_target

def update_target
   self.target.save!
end

Test:

require 'spec_helper'
describe LabelsController do
  before(:each) do
    controller.stub(:current_user).and_return(mock_model(User))
    stub_request(:any, "www.example.com").to_return(status: 200)
  end
  describe "#create" do
    context "label is new" do
      it "creates a new label" do
        attributes = {
          label: {
            name: "test",
            labeling: {
              target_type: "Link", target_id: 1
            }
          }
        }
        response.status.should == 200
        post :create, attributes[:label], format: :json
      end
    end
  end
end

Labeling controller:

  def create
    label = Label.find_by_name(params[:name])

    labeling = label.labelings.build do |lb|
      lb.user_id     = current_user.id
      lb.target_type = params[:labeling][:target_type]
      lb.target_id   = params[:labeling][:target_id]
    end

    if labeling.save
      render json: {
        name: label.name,
        id: label.id,
        labeling: {
          id: labeling.id
        }
      }
    end
  end

Upvotes: 4

Views: 4180

Answers (1)

Erez Rabih
Erez Rabih

Reputation: 15788

By the looks of it you don't have a Target with ID 1 on the database, so where you refer to self.target the returned value is nil. What I'd do in your case is first create a target and then pass its id to the attributes hash:

target = Traget.create!
attributes = {
          label: {
            name: "test",
            labeling: {
              target_type: "Link", target_id: target.id
            }
          }
        }

This way you don't need to stub anything. If you really must stub the method you can use RSpecs any_instance method:

Labeling.any_instance.stub(:update_target).and_return(true)

Upvotes: 1

Related Questions