Ruby on Rails Rspec undefined method host error - ruby-on-rails

When I try to write test to a method in controller I received undefined method host error. Here is the example code blocks below
In rspec file:
require 'rails_helper'
RSpec.describe FooController, type: :controller do
before do
#controller = FooController.new
#controller.params = ActionController::Parameters.new({ foo_id: foo.id, })
#set_foo = #controller.send(:set_foo_data)
end
and in foo controller:
def set_foo_data
#foo_data = {
table_type: :foo,
.
.
data_url: foos_path,
}
end
data_url part causing this issue.
I checked with byebug and data_url was nil.

The reason this doesn't work is that controllers are Rack middleware and expect to be initialized with a request. Its also just not how you should be coding or testing your code in the first place. Bin it.
Controller specs use the get, post, etc methods that actually create an instance of the controller with a mocked request.
get :foo would then call the foo method directly on the controller instance. You do not initialize controllers directly. If you feel tempted to do this its a very good sign you're doing something very wrong.
Unit testing controllers with controller specs is an extremely flawed approach that's discouraged by both the RSpec and Rails teams - you're mocking out huge parts of the application like the middleware and routes and it lets so many bugs through your tests.
The modern way to test a Rails application is to just test the actions of your controller by sending HTTP requests. This means that you should ONLY test the methods that actually correspond to a route and test your application through the response it provides (the headers and body) and eventually the side effects. In RSpec-Rails this is provided through request, feature and system specs.
Everything else in your controller like this method should be private - and you don't test privates.

Related

IntegrationTest with Mocha, stub HelperMethod (Ruby)

I got a helper method:
has_permission?
In a Module called:
module ApplicationHelper
Inside app/helpers.
I also have an IntegrationTest which includes it:
include ApplicationHelper
My Integration test calls one of my controllers via get request.
On call I want to test if my integration test arrives at a certain method.
On this way is has to pass a few of the methods, one of those being the
has_permission?
In order to make sure this method passes I wanted to stub it.
Object.any_instance.expects(:has_permission?).returns(false)
Doesn't work
ApplicationHelper.expects(:has_permission?).returns(false)
Doesn't work either because it's not a static method.
Is there a way I can stub the helpers non-static method within the test so I can make it return false in all cases?
The test:
test "test try to edit without permission" do
#curr = users(:me)
sign_in #curr
SellingController.expects(:validate).never
post enable_update_user_selling_path(id: #user, params: {user: {sell: "1"}})
end
Stumbled across this when trying to work out how to stub an ApplicationHelper method in an ActionDispatch::IntegrationTest in Rails 5; not sure if that's exactly what you're trying to achieve but I ended up doing something like this
MyController.view_context_class.any_instance.expects(:my_method).returns(true)
It looks as though since Rails 5, helper methods aren't simply mixed into the controller classes directly hence the view_context_class bit.
Seems to work, hopefully this will be helpful to someone!
Forgot to post how I ended up solving this:
SellingController.any_instance.stubs(:has_permission?).returns(false)

What does specifying the type in an RSpec actually affect?

I have never been sure what the difference between these options are
RSpec.describe V2::DirectMessagesController, type: :controller
vs
RSpec.describe V2::DirectMessagesController, type: :request
Or where to even look to figure it out
Request specs provide a thin wrapper around Rails' integration tests, and are designed to drive behavior through the full stack, including routing
(provided by Rails) and without stubbing (that's up to you).
A controller spec is an RSpec wrapper for a Rails functional test
(ActionController::TestCase::Behavior).
It allows you to simulate a single http request in each example, and then
specify expected outcomes such as:
rendered templates
redirects
instance variables assigned in the
controller to be shared with the view
cookies sent back with the
response
Controller spec docs: https://relishapp.com/rspec/rspec-rails/docs/controller-specs
Request spec docs: https://relishapp.com/rspec/rspec-rails/docs/request-specs/request-spec

Unable to stub current user using restful authentication plugin

I'm working on a Rails 2.1 app. This app uses 'rspec', '1.2.9' and 'rspec-rails', '1.2.9' . This app uses restful authentication plugin. There is a :login_required before filter method that I have in my Application Controller which basically does the authentication check before allowing access to controller method.
I referred to some older stack overflow(so) questions where users had similar issues, PFB the errors that I got when I tried each of the recommended solutions with respect to those questions.
1 How to stub Restul-authentication's current_user method?
The error I got -
undefined method `stub!' for #<User:0xf5a9c07c>
2 Rails, Restful Authentication & RSpec - How to test new models that require authentication
With respect to this question, I added the below line of code as given in the second answer to the same.
The error I got when I added the above line is -
controller.stub!(:authenticate).and_return(true)
undefined method `stub!' for Controller_NameController:Class
On closer observation, I find that something's wrong with why my test cases aren't able to pick up the stub method.
Here's my code below that I've written to call a specific action within a controller.
Here Controller_Name refers to a controller name like Users controller and in that sense the Controller_NameController basically will stand for UsersController.
require 'spec_helper'
describe Controller_NameController do
describe "What action to test" do
describe "what specific field to update as part of action" do
before do
#Controller_NameController.stub!(:login_required).and_return(true) #this line throws error wrt point 2
#does some stuff
end
it "should update the flag by calling the update method" do
##user_session = login_as(stub_model(User))
#UserSession.stubs(:new).returns(#user_session) - these two lines throws errors wrt point 1
put :update_flag, :id => #obj.id, :obj => {:flag_name => 1}
#obj.updated_at.hour.should == Time.now.hour
end
end
end
end
I'm not sure what's exactly wrong here. Any pointers on how to get this working would be very helpful.
Thank you.

How to mock the redirect to an external URL for a integration/acceptance test?

In my Rails 3 application I have a controller with the following actions (code simplified):
def payment
redirect_to some_url_of_an_external_website
end
# the external website redirects the browser to this action when the payment is done
def payment_callback
#subscription = Subscription.new(:subscription_id => params[:subscription_id])
...
end
In my acceptance test (using steak and RSpec 2), I want to avoid the redirection to this external URL when capybara follows the link pointing to the payment action. Basically I want to mock the route helper payment_path so that it directly points to the payment_call_path with the appropriate subscription_id parameter.
Is this the correct way to do it? If so, how can I mock the payment_path (could not find how to do it)?
Whilst I usually try to avoid mocking in integration tests, here you can do something like this:
MyController.stub!(:payment).and_return('payment received').
Using class_eval as mentioned above will lead to that method being permanently stubbed out across your entire run (if you want this, I'd suggest stubbing it in spec_helper [that's assuming you use a spec_helper]). I find using rspec's mocking/stubbing stuff preferable anyway.
I'm not sure if this is the 'correct' way of doing this, but you can stub any of your application's code to return what you need for your test. So somewhere in your RSpec test you can do something like
MyController.class_eval do
def payment
'payment received'
end
end
Here is an example (see section 'Session Helper Methods') where the #admin? method in ApplicationController is stubbed when a custom RSpec helper module is included into the example group.

Use request helpers outside of controller specs

I'd like to include the request helpers (from ActionDispatch::Integration::RequestHelpers [ApiDock], like post and xhr methods) also in some specs outside of my controller specs. The problem is that these request helpers are only included in spec/controller and when a controller is described.
What do I have to include/require in those specs?
I am using RSpec 2 and Rails 3.
I just solved the problem by including the below code in my acceptance helper. If you are not Steak then just simply put it in spec helper or require it from somewhere else. post and xhr methods are now available in that spec regardless in what spec it is or in what directory you are.
The code is derived from RSpec::Rails::RequestExampleGroup
RSpec::Core::ExampleGroup.class_eval do
include ActiveSupport::Concern
include ActionDispatch::Integration::Runner
include RSpec::Rails::BrowserSimulators
def app
::Rails.application
end
def last_response
response
end
end
I know it's 4 years later and many things have of course changed, but since I stumbled on this question while searching how to make other tests behave like controller tests (and thus have post and get methods and the like) I wanted to point out this solution that works with RSpec 3: if you add this to the spec_helper
config.include RSpec::Rails::RequestExampleGroup, type: :request, example_group: { file_path: /spec\/(api|integration)/
it will make all tests in the given path have support for controller methods.

Resources