简体   繁体   中英

Rails 4 engine controller redirect fails unit testing

I am building a Rails 4 engine that provides some controllers and models that will then be used by several of our apps. I am in the process or writing the unit tests, and I am having problems with the actions in the controllers that make a redirect_to .

In the controller that I am testing, I have the following actions:

def index
end

def new
  @block = GlobalIpBlock.new
end

def create
  @block = GlobalIpBlock.new(create_params)
  if @block.save
    flash[:success] = "The IP has been successfully blocked."
    redirect_to action: 'index'
  else
    render 'new'
  end
end

and in the controller test I have these two tests:

test "should get new block" do
  get :new, use_route: :watchdog
  assert_response :ok
  assert_not_nil assigns(:block)
end

test "should create global ip block" do
  assert_difference('GlobalIpBlock.count') do
    post :create, block: {some_param: 'some value'}, use_route: :watchdog
  end

  assert_redirected_to :index
end

The first test passes but the second throws an error:

ActionController::UrlGenerationError: No route matches {:action=>"index"}

I have no routes created in the engine and in the routes of the dummy test app it only mounts the engine. The reason for that is that I want the hosting apps to provide their own routes to the controllers/actions of the engine.

Still, this doesn't seems to be the issue here since the test for the action new passes. Furthermore, I have tried creating the routes in the engine by doing:

resources :global_ip_blocks, except: [:edit, :update]

but that didn't help, neither did doing that in the routes of the dummy test app.

I am guessing the redirect_to is not finding the route in the same way that removing use_route: :watchdog from the get/post in the tests fail but how can I fix that? Is there something like a global way of telling unit tests to use_route: :watchdog ?

You should be able to fix this using:

class MyControllerTest < ActionController::TestCase
  def setup
    @routes = MyEngine::Engine.routes
  end
end

Also, look out for the deprecation notice in the logs due to the use of use_route which is like:

DEPRECATION WARNING: Passing the use_route option in functional tests are deprecated. Support for this option in the process method (and the related get , head , post , patch , put and delete helpers) will be removed in the next version without replacement. Functional tests are essentially unit tests for controllers and they should not require knowledge to how the application's routes are configured. Instead, you should explicitly pass the appropiate params to the process method. Previously the engines guide also contained an incorrect example that recommended using this option to test an engine's controllers within the dummy application. That recommendation was incorrect and has since been corrected. Instead, you should override the @routes variable in the test case with Foo::Engine.routes . See the updated engines guide for details.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM