I"m attempting to test my application_helper's yield_for method but I don't know the best way to go about it. I've tried the code below but get the following error:
Failure/Error: self.stub(:content_for).with(:foo).and_return('bar')
Stub :content_for received unexpected message :with with (:foo)
application_helper.rb
def yield_for(content_sym, default = '')
content_for?(:content_sym) ? content_for(content_sym) : default
end
application_helper_spec.rb
describe '#yield_for' do
it 'should fetch the yield' do
self.stub(:content_for).with(:foo).and_return('bar')
helper.yield_for(:foo).should == 'bar'
end
end
I'm using rspec (3.1.0) and it should work with:
describe '#yield_for' do
it 'should fetch the yield' do
helper.content_for(:foo, 'bar')
expect(helper.yield_for(:foo)).to eq('bar')
end
end
Try making the stub on the helper
it 'should fetch the yield' do
helper.stub(:content_for).with(:foo).and_return('bar')
helper.yield_for(:foo).should == 'bar'
end
Got your test passing with this
def yield_for(content_sym, default = '')
content_for(content_sym) ? content_for(content_sym) : default
end
Related
I've been trying to stub a private module method for the whole day now but with not progress.
Here is a snippet of my application controller class
class ApplicationController < ActionController::Base
include Cesid::Application
end
Cesid > Application.rb
module Cesid
module Application
extend ActiveSupport::Concern
included do
before_action :track_marketing_suite_cesid, only: [:new]
end
private
def track_marketing_suite_cesid
return unless id_token_available?
## #cesid_auth = Auth.new(#id_token)
#cesid_auth = Auth.new(id_token)
return unless #cesid_auth.present? && #cesid_auth.valid?
#cesid_admin = Admin.where(email: #cesid_auth.email).first_or_initialize
end
def id_token_available?
## #id_token.present?
id_token.present?
end
def id_token
#id_token ||= id_token_param
end
def id_token_param
cookies[:id_token]
end
end
end
Now, I'm trying to create a simple unit test for the method
id_token_available?
And I am just trying to set the id_token_param to a random value.
I've tried using this code as stated Is there a way to stub a method of an included module with Rspec?
allow_any_instance_of(Cesid).to receive(:id_token_param).and_return('hello')
but I just get this error
NoMethodError:
undefined method `allow_any_instance_of' for #<RSpec::ExampleGroups::CesidApplication::CesidAuthorizations::GetCesidApplication:0x00007fa3d200c1c0> Did you mean? allow_mass_assignment_of
Rspec file
require 'rails_helper'
describe Cesid::Application, :type => :controller do
describe 'cesid application' do
before do
allow_any_instance_of(ApplicationController).to receive(:id_token_param).and_return('hello')
end
it 'returns true if the id_token is present' do
expect(Cesid::Application.send('id_token_available?')).to eql(true)
end
end
end
Rspec version
3.5.4
This is honestly starting to drive me crazy
I see three issues:
You call allow_any_instance_of in a context in which it is not defined. allow_any_instance_of can be used in before blocks. I need to see your RSpec code to be more specific.
Actually your code is called on the ApplicationController, not on the module, therefore you need to change your stub to
allow_any_instance_of(ApplicationController).to receive(:id_token_param).and_return('hello')
Currently id_token_param will not be called at all, because id_token_available? checks the instance variable and not the return value of the id_token method that calls the id_token_param. Just change the id_token_available? to:
def id_token_available?
id_token.present?
end
There's a much better way of going about this test. The type: :controller metadata on your spec gives you an anonymous controller instance to work with.
Here's an example of how you could write this to actually test that the before_action from your module is used:
describe Cesid::Application, type: :controller do
controller(ApplicationController) do
def new
render plain: 'Hello'
end
end
describe 'cesid before_action' do
before(:each) do
routes.draw { get 'new' => 'anonymous#new' }
cookies[:id_token] = id_token
allow(Auth).to receive(:new).with(id_token)
.and_return(instance_double(Auth, valid?: false))
get :new
end
context 'when id token is available' do
let(:id_token) { 'hello' }
it 'sets #cesid_auth' do
expect(assigns(:cesid_auth)).to be_present
end
end
context 'when id token is unavailable' do
let(:id_token) { '' }
it 'does not set #cesid_auth' do
expect(assigns(:cesid_auth)).to be_nil
end
end
end
end
I am writing a controller spec to verify this private method and I get the error Module::DelegationError: ActionController::RackDelegation but I am lost as how to fix this. The best example I have found has been http://owowthathurts.blogspot.com/2013/08/rspec-response-delegation-error-fix.html.
How can I get the unverified spec to pass? I want to make sure the 401 is returned.
Method
def validate_api_request
return four_oh_one unless api_request_verified?(request)
end
Current Spec
describe Api::ApiController, type: :controller do
describe '#validate_api_request' do
it 'verified' do
allow_any_instance_of(described_class).to receive(:api_request_verified?).and_return(true)
expect(subject.send(:validate_api_request)).to be_nil
end
it 'unverified' do
allow_any_instance_of(described_class).to receive(:api_request_verified?).and_return(false)
allow(controller).to receive(:redirect_to)
binding.pry
end
end
end
I'm using Rails 4.
If anyone is working on a similar issue writing controller specs, here is how I solved this based on these 2 guides: http://codegur.com/22603728/test-user-authentication-with-rspec and https://gayleforce.wordpress.com/2012/12/01/testing-rails-before_filter-method/.
describe Api::ApiController, type: :controller do
describe '#validate_api_request' do
controller(Api::ApiController) do
before_filter :validate_api_request
def fake
render text: 'TESTME'
end
end
before do
routes.draw { get 'fake', to: 'api/api#fake' }
end
it 'verified' do
allow_any_instance_of(described_class).to receive(:api_request_verified?).and_return(true)
expect(subject.send(:validate_api_request)).to be_nil
end
it 'unverified' do
allow_any_instance_of(described_class).to receive(:api_request_verified?).and_return(false)
get 'fake'
expect(response.status).to be(401)
end
end
end
There is the following spec:
describe 'Some title' do
before do
session[:state] = "12334"
get '/api/v1/menus', format: :json
end
it 'some text' do
expect(response).to be_success
json = JSON.parse(response.body)
puts json
end
end
It code tests the following controller's action:
class Api::V1::MenusController < ActionController
def index
render json: session
end
end
But I've got the following exception: "undefined method `session' for nil:NilClass". How can I fix it? How can I make a new example of a session? Thanks in advance.
Try this:
describe 'Some title', :type => :controller do
RSpec needs to know you are doing "controller things" in your test. You indicate this as above or by placing the test in spec/controllers.
That's certainly trivial but can't figure out what goes wrong.
Helper : app/helpers/bookings_helper.rb
module BookingsHelper
def booking_price(booking)
"something"
end
end
Helper spec : spec/helpers/bookings_helper_spec.rb
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe BookingsHelper do
describe "#booking_price" do
helper.booking_price.should == 'something'
end
end
Error
/Library/Ruby/Gems/1.8/gems/activesupport-3.0.4/lib/active_support/whiny_nil.rb:48:in `method_missing': undefined method `booking_price' for nil:NilClass (NoMethodError)
Try using it instead of describe for the inside block:
describe BookingsHelper do
it "#booking_price" do
helper.booking_price.should == 'something'
end
end
Using Rspec with Factory Girl. Trying to check out what data is being assigned in my controller (and test against it). Every post I've read says I should be able to get something out of assigns() but it keeps returning nill
Controller
def index
#stickies = Sticky.where(:user_id => current_user.id)
end
Spec
it "should assign stickies" do
foo = assigns(:stickies)
puts "foo = #{foo}"
end
Output
foo =
Am I using the wrong syntax? Is there a better way to do this? Thanks!!
You have to invoke the action first
describe StickiesController do
describe "GET index" do
it "should assign stickies" do
get :index
assigns(:stickies).should_not be_nil
end
end
end
If you are using the rspec > 2.99 you can use:
expect(assigns(:stickies)).not_to be_nil