Chcę sprawdzić wiele zmian w modelu podczas przesyłania formularza w specyfikacji funkcji. Na przykład chcę się upewnić, że nazwa użytkownika została zmieniona z X na Y i że zaszyfrowane hasło zostało zmienione o dowolną wartość.
Wiem, że jest już kilka pytań na ten temat, ale nie znalazłem dla mnie odpowiedniej odpowiedzi. Najdokładniejsza odpowiedź wydaje się podobna do ChangeMultiple
dopasowania Michaela Johnstona: Czy jest możliwe, aby RSpec spodziewał się zmiany w dwóch tabelach? . Wadą jest to, że sprawdza się tylko pod kątem wyraźnych zmian ze znanych wartości na znane wartości.
Stworzyłem pseudo kod pokazujący, jak moim zdaniem mógłby wyglądać lepszy dopasowujący:
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
)
Stworzyłem również podstawowy szkielet ChangeMultiple
dopasowania w następujący sposób:
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
Ale teraz już otrzymuję ten błąd:
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'
Każda pomoc w tworzeniu tego niestandardowego dopasowania jest bardzo cenna.
źródło
.and change { @something }.by(0)
.should_not
dla każdego, kto jej potrzebujeJeśli chcesz sprawdzić, czy wiele rekordów nie zostało zmienionych, możesz odwrócić dopasowanie za pomocą
RSpec::Matchers.define_negated_matcher
. Więc dodajRSpec::Matchers.define_negated_matcher :not_change, :change
na początek twojego pliku (lub do twojego
rails_helper.rb
), a następnie możesz łączyć za pomocąand
:expect{described_class.reorder}.to not_change{ruleset.reload.position}. and not_change{simple_ruleset.reload.position}
źródło
Zaakceptowana odpowiedź nie jest w 100% poprawna, ponieważ pełna obsługa dopasowywania złożonego dla
change {}
została dodana w RSpec w wersji 3.1.0 . Jeśli spróbujesz uruchomić kod podany w zaakceptowanej odpowiedzi z RSpec w wersji 3.0, pojawi się błąd.Aby użyć dopasowań złożonych z
change {}
, istnieją dwa sposoby;def supports_block_expectations?; true; end
doRSpec::Matchers::BuiltIn::Compound
klasy, albo przez małpę łatając ją, albo bezpośrednio edytując lokalną kopię klejnotu. Ważna uwaga: ten sposób nie jest całkowicie równoważny z pierwszym,expect {}
blok działa w ten sposób wielokrotnie!Żądanie ściągnięcia, które dodało pełną obsługę funkcji dopasowań złożonych, można znaleźć tutaj .
źródło
Odpowiedź BroiSatse jest najlepsza, ale jeśli używasz RSpec 2 (lub masz bardziej złożone dopasowania, takie jak
.should_not
), ta metoda również działa: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}
źródło