Rspec: Stub method that is in the controller

Can I learn how to stub the method that is in the controller creation method? I need to write a specification for this, but I got these errors. I need to verify that the create method in the controller must execute the validate_fbid method before creating a new company record in the model.

Error:

1) Companies new company create with valid information#validate_fbid should have correct parameters and return value Failure/Error: CompaniesController.create.should_receive(:validates_fbid).with(company) NoMethodError: undefined method `create' for CompaniesController:Class # ./spec/requests/companies_spec.rb:38:in `block (5 levels) in <top (required)>' 2) Companies new company create with valid information#validate_fbid should fbid validation passed Failure/Error: CompaniesController.create.stub(:validates_fbid).and_return('companyid') NoMethodError: undefined method `create' for CompaniesController:Class # ./spec/requests/companies_spec.rb:43:in `block (5 levels) in <top (required)>' 

CompaniesController

 def create company = Company.new(params[:company]) verifyfbid = validate_fbid(company) if verifyfbid != false if company.fbid.downcase == verifyfbid.downcase if company.save @message = "New company created." redirect_to root_path else @message = "Company create attempt failed. Please try again." render 'new' end else @message = "Company create attempt failed. Invalid facebook id." render 'new' end else @message = "Company create attempt failed. No such facebook id." render 'new' end end private def validate_fbid(company) uri = URI("http://graph.facebook.com/" + company.fbid) data = Net::HTTP.get(uri) username = JSON.parse(data)['username'] if username.nil? return false else "#{username}" end end 

Requests / companies_spec.rb

 context "#validate_fbid" do #validate fbid let(:company){ Company.new(name:'Example Company', url: 'www.company.com', fbid: 'companyid', desc: 'Company desc' )} it "should have correct parameters and return value" do CompaniesController.create.should_receive(:validates_fbid).with(company) .and_return('companyid') end it "should fbid validation passed" do CompaniesController.create.stub(:validates_fbid).and_return('companyid') company.fbid.should_not be_nil company.fbid.should == 'companyid' company.save expect { click_button submit }.to change(Company, :count).by(1) end end 
+6
source share
4 answers

You do not want to stub the method when it is the subject of your test case

 context "#validate_fbid" do #test the function here #don't stub end 

when you check the create action in the controller, you can stub "validate_fbid"

 describe "post create" do ... CompaniesController.any_instance.stub(:validates_fbid).and_return('companyid') ... end 

Hope this helps.

+15
source

When code is difficult to test, it is usually because it is complex.

You should reorganize this code as follows:

  • move the validation logic to the new “service class”, which is solely responsible for verifying the company on facebook
  • this will make the functionality check independent of the web tier and much easier to test
  • make spec for a service class that will test this code in isolation (without controllers)
  • clearing the logic controller - you do not want to have logic inside your controllers (thumb rule: one level of the nesting layout)
  • specification for the controller will also be easier

The controller code might look something like this:

 def create company = Company.new(params[:company]) verified = FbCompanyVerifier.new.verify(company) if verified and company.save # success logic else # fail logic end end 
+5
source

If you are testing a controller, you can directly contact the controller:

 controller.stub(:message) { 'this is the value to return' } 
+1
source

Here is the recommended syntax for Rspec 3 (3.3):

  • allow_any_instance_of(CompaniesController).to receive(:validates_fbid).and_return("companyid")

or

  • expect_any_instance_of(CompaniesController).to receive(:validates_fbid).and_return("companyid")

source: https://relishapp.com/rspec/rspec-mocks/docs/working-with-legacy-code/any-instance

+1
source

Source: https://habr.com/ru/post/950499/


All Articles