Ich arbeite an einer Anwendung, die in erster Linie als API serviert wird (abgesehen von einigen kleineren Ansichten, wie Session/Registrierung, die "Standard" sein wird). Ich mag den Ansatz, der in Railscast #350: Versioning an API finalisiert wurde, und folgte ihm so. Meine Strecken wie folgt aussehen:So testen Sie Routenbeschränkungen mit 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
In jeder Strecke, mein Constraint ist ein neues ApiConstraints Objekt, das in meinem ./lib
-Ordner befindet. Die Klasse sieht so aus:
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
Jetzt, wenn Sie manuell testen, funktioniert alles wie erwartet. In meiner API habe ich möglicherweise zwischen 5 und 10 Controller pro Version und möchte nicht testen, dass die API-Einschränkungen für jeden einzelnen Controller funktionieren, da dies keinen Sinn ergibt. Ich suche nach einer Spezifikationsdatei, die meine API-Einschränkungen testet, aber ich bin mir nicht sicher, wo ich diese Spezifikation platzieren soll.
Ich habe versucht, das Hinzufügen einer spec/routing/api_spec.rb
Datei Dinge zu testen, aber es ist nicht richtig funktioniert, wie es beklagt, dass einige Dinge nicht vorgesehen sind, etwa so:
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
Die oben einen Fehler wirft, obwohl Der Controller stimmt überein. Es schlägt mit dem folgenden Fehler:
The recognized options <{"format"=>"json", "action"=>"index", "controller"=>"api/v1/posts"}>
did not match <{"controller"=>"api/v1/posts"}>,
difference: <{"format"=>"json", "action"=>"index"}>.
Beachten Sie, dass der Controller korrekt bestimmt wurde, aber da will ich nicht für das Format und Wirkung in diesem Test testen, es Fehler aus. Ich möchte es 3 „API-Spezifikationen“ sein:
- Es sollte Route eine unversionierte Anfrage auf die neueste Version
- Auf dem JSON-Format standardmäßig sollte, wenn keine angegeben ist
- Es sollte eine spezifizierte Rück API Version wenn angefordert
Hat jemand Erfahrung mit dem Schreiben von Spezifikationen für diese Art von Routen? Ich möchte keine Spezifikationen für jeden Controller innerhalb der API hinzufügen, da sie für diese Funktionalität nicht verantwortlich sind.
Ja, das ist richtig. Idealerweise möchte ich drei Tests in meiner API-Spezifikationsdatei, eine zum Testen des Standardformats, eine zum Testen, dass sie zu einem gültigen Controller routet, wenn keine Version angegeben ist, und eine zum Testen, dass sie zur richtigen Version routet, wenn a Version ist angegeben. –
Nun, mit 'route_to' müssen Sie spezifischere Erwartungen wie' expect (: get => "/api/posts.json"').route_to (: controller =>" api/v1/posts ",: action => "index",: format => "json") '. Mit den standardmäßigen rspec-rails-Matchern ist das leider nicht der Fall. – gregates
Das Problem dabei ist, dass jede Spezifikation die Logik von jeder anderen Spezifikation testen wird. Es ist im Wesentlichen alle Spezifikationen in einen Test zu rollen, der nicht ideal ist. –