They don't seem to be accessible from ActionView::TestCase
5 Answers
That's right, helper methods are not exposed in the view tests - but they can be tested in your functional tests. And since they are defined in the controller, this is the right place to test them. Your helper method is probably defined as private
, so you'll have to use Ruby metaprogramming to call the method.
app/controllers/posts_controller.rb:
class PostsController < ApplicationController
private
def format_something
"abc"
end
helper_method :format_something
end
test/functional/posts_controller_test.rb:
require 'test_helper'
class PostsControllerTest < ActionController::TestCase
test "the format_something helper returns 'abc'" do
assert_equal 'abc', @controller.send(:format_something)
end
end

- 76,434
- 37
- 167
- 198

- 12,163
- 2
- 42
- 48
-
6This doesn't test that format_something is exposed as a helper though. `send(:format_something)` will work without `helper_method :format_something`. I'm trying to find a solution to this myself. – PhilT Jan 17 '13 at 15:35
This feels awkward, because you're getting around encapsulation by using send on a private method.
A better approach is to put the helper method in a module in the /controller/concerns directory, and create tests specifically just for this module.
e.g. in app controller/posts_controller.rb
class PostsController < ApplicationController
include Formattable
end
in app/controller/concerns/formattable.rb
module Concerns
module Formattable
extend ActiveSupport::Concern # adds the new hot concerns stuff, optional
def format_something
"abc"
end
end
end
And in the test/functional/concerns/formattable_test.rb
require 'test_helper'
# setup a fake controller to test against
class FormattableTestController
include Concerns::Formattable
end
class FormattableTest < ActiveSupport::TestCase
test "the format_something helper returns 'abc'" do
controller = FormattableTestController.new
assert_equal 'abc', controller.format_something
end
end

- 1,232
- 16
- 21
You could test @controller.view_context
from your functional/controller tests. This method is available in Rails 3, 4, and 5, as far as I can tell.
app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
helper_method :current_user
# ...
end
test/controllers/application_controller_test.rb
require 'test_helper'
class ApplicationControllerTest < ActionController::TestCase
test 'current_user helper exists in view context' do
assert_respond_to @controller.view_context, :current_user
end
end
If you didn't want to test one of your controller subclasses, you could also create a test controller to verify that the method in the view_context is the same one from the controller and not from one of your view helpers.
class ApplicationControllerHelperTest < ActionController::TestCase
class TestController < ApplicationController
private
def current_user
User.new
end
end
tests TestController
test 'current_user helper exists in view context' do
assert_respond_to @controller.view_context, :current_user
end
test 'current_user returns value from controller' do
assert_instance_of User, @controller.view_context.current_user
end
end
Or, more likely, you'd want to be able to test the helper in the presence of a request.
class ApplicationControllerHelperTest < ActionController::TestCase
class TestController < ApplicationController
def index
render plain: 'Hello, World!'
end
end
tests TestController
def with_routing
# http://api.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-with_routing
# http://guides.rubyonrails.org/routing.html#connecting-urls-to-code
super do |set|
set.draw do
get 'application_controller_test/test', to: 'application_controller_test/test#index'
end
yield
end
end
test 'current_user helper exists in view context' do
assert_respond_to @controller.view_context, :current_user
end
test 'current_user returns value from controller' do
with_routing do
# set up your session, perhaps
user = User.create! username: 'testuser'
session[:user_id] = user.id
get :index
assert_equal user.id, @controller.view_context.current_user.id
end
end
end

- 6,618
- 3
- 44
- 42
I've struggled with this for a bit, because the accepted answer didn't actually test whether the method was exposed as a helper method.
That said, we can use the #helpers
method to get a proxy for testing.
For example:
class FooController < ApplicationController
private
def bar
'bar'
end
helper_method :bar
end
Can be tested with:
require 'test_helper'
class FooControllerTest < ActionController::TestCase
test 'bar is a helper method' do
assert_equal 'bar', @controller.helpers.bar
end
end

- 170,779
- 38
- 263
- 309
Indeed they're not. The view tests are specifically for the views. They don't load the controllers.
You should mock this method and make it return whatever is appropriate depending of your context.

- 31,924
- 13
- 86
- 94
-
"You should mock this method and make it return whatever is appropriate" - well I actually want to test the method :-) – Teflon Ted Mar 15 '10 at 15:45
-
Yeah but testing an helper method inside of a view isn't the appropriate way of doing so :) – Damien MATHIEU Mar 16 '10 at 07:36
-
"testing an helper method inside of a view isn't the appropriate way of doing so" - then why does the Rails scaffold generate helper tests based on ActionView::TestCase ? :-( and what is the proper way? all I want is to test this method. thanks. – Teflon Ted Mar 16 '10 at 13:45
-
Yes but this method is primarily a controller method. You should test it in your controller/lib. – Damien MATHIEU Mar 16 '10 at 14:46
-
I don't appear to have `controller/lib` in my Rails application. Is this something new?! – PhilT Jan 17 '13 at 15:37