Ich möchte beim Senden eines Formulars in einer Feature-Spezifikation nach vielen Änderungen in einem Modell suchen. Ich möchte beispielsweise sicherstellen, dass der Benutzername von X in Y geändert wurde und dass das verschlüsselte Kennwort um einen beliebigen Wert geändert wurde.
Ich weiß, dass es dazu bereits einige Fragen gibt, aber ich habe keine passende Antwort für mich gefunden. Die genaueste Antwort scheint hier der ChangeMultiple
Matcher von Michael Johnston zu sein: Kann RSpec Änderungen in zwei Tabellen erwarten? . Sein Nachteil ist, dass man nur nach expliziten Änderungen von bekannten Werten zu bekannten Werten sucht.
Ich habe einen Pseudocode erstellt, wie ein besserer Matcher aussehen könnte:
expect {
click_button 'Save'
}.to change_multiple { @user.reload }.with_expectations(
name: {from: 'donald', to: 'gustav'},
updated_at: {by: 4},
great_field: {by_at_leaset: 23},
encrypted_password: true, # Must change
created_at: false, # Must not change
some_other_field: nil # Doesn't matter, but want to denote here that this field exists
)
Ich habe auch das Grundgerüst des ChangeMultiple
Matchers wie folgt erstellt:
module RSpec
module Matchers
def change_multiple(receiver=nil, message=nil, &block)
BuiltIn::ChangeMultiple.new(receiver, message, &block)
end
module BuiltIn
class ChangeMultiple < Change
def with_expectations(expectations)
# What to do here? How do I add the expectations passed as argument?
end
end
end
end
end
Aber jetzt bekomme ich schon diesen Fehler:
Failure/Error: expect {
You must pass an argument rather than a block to use the provided matcher (nil), or the matcher must implement `supports_block_expectations?`.
# ./spec/features/user/registration/edit_spec.rb:20:in `block (2 levels) in <top (required)>'
# /Users/josh/.rvm/gems/ruby-2.1.0@base/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load'
# /Users/josh/.rvm/gems/ruby-2.1.0@base/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `block in load'
Jede Hilfe bei der Erstellung dieses benutzerdefinierten Matchers wird sehr geschätzt.
quelle
.and change { @something }.by(0)
.should_not
für jeden zu funktionieren , der sie brauchtWenn Sie testen möchten, dass mehrere Datensätze nicht geändert wurden, können Sie einen Matcher mithilfe von invertieren
RSpec::Matchers.define_negated_matcher
. Also, füge hinzuRSpec::Matchers.define_negated_matcher :not_change, :change
an den Anfang Ihrer Datei (oder an Ihre
rails_helper.rb
) und dann können Sie verketten mitand
:expect{described_class.reorder}.to not_change{ruleset.reload.position}. and not_change{simple_ruleset.reload.position}
quelle
Die akzeptierte Antwort ist nicht 100% korrekt, da die vollständige Unterstützung für Compound Matcher für
change {}
in RSpec Version 3.1.0 hinzugefügt wurde . Wenn Sie versuchen, den in der akzeptierten Antwort angegebenen Code mit der RSpec-Version 3.0 auszuführen, wird eine Fehlermeldung angezeigt.Um zusammengesetzte Matcher mit zu verwenden
change {}
, gibt es zwei Möglichkeiten;def supports_block_expectations?; true; end
derRSpec::Matchers::BuiltIn::Compound
Klasse etwas hinzufügen , indem Sie sie entweder mit einem Affen patchen oder die lokale Kopie des Edelsteins direkt bearbeiten. Ein wichtiger Hinweis: Dieser Weg entspricht nicht vollständig dem ersten, derexpect {}
Block läuft auf diese Weise mehrmals!Die Pull-Anfrage, die die volle Unterstützung der Compound-Matcher-Funktionalität bietet, finden Sie hier .
quelle
Die Antwort von BroiSatse ist die beste, aber wenn Sie RSpec 2 verwenden (oder komplexere Matcher wie haben
.should_not
), funktioniert diese Methode auch:lambda { lambda { lambda { lambda { click_button 'Save' @user.reload }.should change {@user.name}.from('donald').to('gustav') }.should change {@user.updated_at}.by(4) }.should change {@user.great_field}.by_at_least(23) }.should change {@user.encrypted_password}
quelle