Отправка в конечную точку не в том же модуле в модульном тестировании

#ruby-on-rails

#ruby-on-rails

Вопрос:

Я работаю над устаревшим проектом Rails 2. У меня MyController в Foo модуле:

 module Api::Foo
  class MyController < ::ActionController::Base
    def doJob
      puts "do the job"
    end
  end
end
  

В routes.rb у меня есть:

 map.connect 'api/foo/dojob', :controller => 'api/foo/my',:action => 'doJob', :conditions => { :method => :post }
  

У меня есть другой контроллер, который находится вне Foo модуля, он находится в Bar модуле:

 module Api::Bar
  class AnotherController < ::ActionController::Base
    def doCalculation
          puts "do the calculation"
    end
  end
end
  

В модульном тестировании AnotherControllerTest , как я могу отправить в конечную api/foo/dojob точку?

 class Api::Bar::AnotherControllerTest < ActionController::TestCase
   def setup
   end

   test 'test internal api call' do
     # how to post to "api/foo/dojob"??
   end
end
  

Я пробовал post "/api/foo/dojob",{} , это не работает.

Комментарии:

1. зачем вам это делать?. Контроллеры не должны вызывать код других контроллеров. Если вам нужен код из одного контроллера в другом, затем извлеките его в module or class .

Ответ №1:

Вы не можете. ActionController::TestCase абстрагирует весь этап фактического выполнения фактического HTTP-запроса.

Что ActionController::TestCase происходит, когда вы делаете get :foo , это создаете экземпляр Api::Bar::AnotherController и передаете ему mocked request . Затем он вызывает #foo метод на контроллере. В то время все это казалось отличной идеей, поскольку позволяло вам копаться во внутренних элементах контроллеров и было немного быстрее.

Он выводит класс из имени класса тестового примера. Хотя вы могли бы переопределить это для создания экземпляра какого-либо другого контроллера, это неправильный ответ на неправильную проблему. Вся идея модульного теста заключается в том, что он тестирует один компонент изолированно.

Для проведения интеграционного тестирования, при котором вы тестируете несколько контроллеров, вам нужен ActionController::IntegrationTest. Интеграционный тест фактически отправляет HTTP-запрос на тестовый сервер. Это также более перспективная стратегия тестирования, поскольку тесты контроллера были отменены.

 require 'test_helper'
class ApiFlowsTest < ActionController::IntegrationTest
   def setup
   end

   test 'test internal api call' do
     post "api/foo/dojob", { foo: 'bar' }
     get  "api/foo/bar"
     assert_response :success
   end
end
  

Комментарии:

1. Кстати, сама идея модульного тестирования контроллеров была глубоко ошибочной и очень сильно вышла из моды в мире rails.