Я работаю над приложением, которое будет в основном использоваться как API (кроме нескольких второстепенных видов, таких как сеанс/регистрация, который будет «стандартным»). Мне нравится подход, который был завершен в Railscast #350: Versioning an API, и поэтому последовал за ним. Мои маршруты выглядеть следующим образом:Как проверить ограничения маршрута с помощью rspec
namespace :api, :defaults => {:format => 'json'} do
scope :module => :v1, :constraints => ApiConstraints.new(:version => 1, :default => false) do
resources :posts, :only => [:create, :show, :destroy, :index]
end
scope :module => :v2, :constraints => ApiConstraints.new(:version => 2, :default => true) do
resources :posts, :only => [:create, :show, :destroy, :index]
end
end
В каждом маршруте, мой Constraint это новый ApiConstraints объект, который находится в моей ./lib
папке. Класс выглядит следующим образом:
class ApiConstraints
def initialize(options)
@version = options[:version]
@default = options[:default]
end
def matches?(req)
@default || req.headers['Accept'].include?("application/vnd.MYAPP.v#{@version}")
end
end
Теперь при тестировании вручную все работает так, как ожидалось. В моем API у меня может быть от 5 до 10 контроллеров на версию и не хочу проверять, что ограничения API работают для каждого отдельного контроллера, поскольку это не имеет никакого смысла. Я ищу один файл спецификации, который проверяет мои ограничения API, но я не уверен, где разместить эту спецификацию.
Я пытался добавить spec/routing/api_spec.rb
файл, чтобы проверить вещи, но это не работает должным образом, так как он жалуется, что некоторые вещи, которые не предусмотрены, например, так:
it "should route an unversioned request to the latest version" do
expect(:get => "/api/posts", :format => "json").to route_to(:controller => "api/v1/posts")
end
выше выдает ошибку, даже если контроллер правильно соответствует. Он не может со следующей ошибкой:
The recognized options <{"format"=>"json", "action"=>"index", "controller"=>"api/v1/posts"}>
did not match <{"controller"=>"api/v1/posts"}>,
difference: <{"format"=>"json", "action"=>"index"}>.
Обратите внимание, что контроллер был правильно определен, но так как я не хочу, чтобы проверить формат и действия в этом тесте, то его ошибки вне. Я хотел бы, чтобы было 3 «API функции»:
- Он должен маршрут неверсированный запрос на последнюю версию
- Он должен по умолчанию в формате JSON, если ничего не указано
- Он должен вернуть указанный Версия API по запросу
Есть ли у кого-нибудь опыт написания спецификаций для этих маршрутов? Я не хочу добавлять спецификации для каждого контроллера внутри API, так как они не отвечают за эту функциональность.
Да, это правильно. В идеале, я хочу три теста в своем файле спецификации api, один для проверки того, что работает формат по умолчанию, один для проверки того, что он маршрутизируется на допустимый контроллер, когда не указана никакая версия, и чтобы проверить, что он перенаправляет правильную версию, когда версия IS. –
Ну, используя 'route_to' вам нужно предоставить более конкретные ожидания, например' ожидать (: get => "/api/posts.json"').to route_to (: controller =>" api/v1/posts ",: action => "index",: format => "json") '. Там, к сожалению, нет способа обойтись со стандартными rspec-rails. – gregates
Проблема в том, что каждая спецификация будет проверять логику из любой другой спецификации. Это, по сути, сводит все спецификации в один тест, что не идеально. –