Pracuję nad aplikacją, która będzie głównie obsługiwana jako API (inne niż kilka mniejszych widoków, takich jak sesja/rejestracja, które będą "standardowe"). Podoba mi się podejście, które zostało sfinalizowane w Railscast #350: Versioning an API, i tak po nim. Moje trasy wyglądać następująco:Jak przetestować ograniczenia trasy za pomocą 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
W każdej trasie, moja ograniczeniem jest nowy ApiConstraints obiekt, który znajduje się w folderze Moje ./lib
. Klasa wygląda następująco:
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
Teraz, podczas testowania ręcznego, wszystko działa zgodnie z oczekiwaniami. W moim API mogę mieć od 5 do 10 kontrolerów na wersję i nie chcę sprawdzać, czy ograniczenia API działają dla każdego pojedynczego kontrolera, ponieważ to nie ma sensu. Szukam jednego pliku spec, który testuje moje ograniczenia API, ale nie jestem pewien, gdzie umieścić tę specyfikację.
Próbowałem dodanie pliku spec/routing/api_spec.rb
przetestować rzeczy, ale to nie działa prawidłowo, ponieważ twierdzi, że niektóre rzeczy nie są, tak jak poniżej:
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
Powyższy zgłasza błąd, chociaż kontroler pasuje poprawnie. Nie powiedzie się z powodu następującego błędu:
The recognized options <{"format"=>"json", "action"=>"index", "controller"=>"api/v1/posts"}>
did not match <{"controller"=>"api/v1/posts"}>,
difference: <{"format"=>"json", "action"=>"index"}>.
Zauważ, że sterownik został prawidłowo ustalone, ale ponieważ nie chcę, aby przetestować dla formatu i działania w tym teście, to błędy na zewnątrz. Chciałbym tam być 3 „specyfikacje API”:
- Powinno trasa niewersjonowany prośba do najnowszej wersji
- Należy domyślnych do formatu JSON, jeśli żadna określona
- Należy zwrócić określony Wersja API na żądanie
Czy ktoś ma doświadczenie w pisaniu specyfikacji dla tego rodzaju tras? Nie chcę dodawać specyfikacji dla każdego kontrolera w interfejsie API, ponieważ nie są odpowiedzialni za tę funkcjonalność.
Tak, to prawda. Idealnie, chcę trzech testów w moim pliku specyfikacji api, jeden do sprawdzenia, czy działa domyślny format, jeden do sprawdzenia, czy kieruje się do poprawnego kontrolera, gdy nie podano żadnej wersji, i do sprawdzenia, czy kieruje się do właściwej wersji, gdy Wersja IS została określona. –
Cóż, używając 'route_to' trzeba zapewnić bardziej konkretne oczekiwania, jak' spodziewać (: get => „/api/posts.json"').to route_to (: controller => "API/v1/posty": action => "index",: format => "json") '. Niestety nie da się tego obejść za pomocą domyślnych dopasowań rspec-rails. – gregates
Problem polega na tym, że każda specyfikacja testuje logikę z każdej innej specyfikacji. Zasadniczo przetwarza wszystkie specyfikacje w jeden test, co nie jest idealne. –