2016-04-19 12 views
6

che sto cercando di fare in modo certo i dati sono rimarrà invariato da una singola azione:Aspettatevi aspettative multipla cambiamento not_to in rspec

expect { 
    # running migration and user reload here 
}.not_to change(user, :avatar_url).from(sample_avatar_url).and change(user, :old_avatar).from(nil) 

sample_avatar_url è una stringa definita all'inizio del file spec.

Fondamentalmente, voglio verificare se il avatar_url e old_avatar rimangono intatti da ciò che sta accadendo nel blocco expect.

L'output dal codice sopra è:

expect(...).not_to matcher.and matcher non è supportato, in quanto crea un po 'di un'ambiguità. Invece, definire le versioni negate di qualsiasi matcher che si desidera negare con RSpec::Matchers.define_negated_matcher e utilizzare expect(...).to matcher.and matcher.

risposta

11

Questo non funziona perché non è chiaro se questo significhi non cambiare il primo e non cambiare il secondo, o non cambiare il primo ma cambiare il secondo. Hai un paio di opzioni per aggirare questo

Dal momento che si sta controllando i valori statici semplicemente non utilizzare il cambiamento

..run migration and user reload.. 
expect(user.avatar_url).to eq(sample_avatar_url) 
expect(user.old_avatar).to eq nil 

o utilizzare define_negated_matcher per creare un matcher not_change

RSpec::Matchers.define_negated_matcher :not_change, :change 
expect { 
    # running migration and user reload here 
}.to not_change(user, :avatar_url).from(sample_avatar_url).and not_change(user, :old_avatar).from(nil) 
+0

Semplificare con il primo esempio fa il trucco. Grazie! – abpetkov

+0

Prego, basta notare che controlla un po 'meno dato che controlla solo che sia impostato un valore specifico, non che non sia stato modificato da qualcos'altro a quel valore - Se questo è sufficiente per il tuo caso d'uso. –

+0

L'inserimento di 'RSpec :: Matchers.define_negated_matcher (: not_change,: change)' in rails_helper.rb ha dato i miei superpoteri RSpec. – Epigene

0

Come dichiarato nella risposta di Thomas, non funziona perché non è chiara la lettura e puoi creare un matcher negato. Un'altra opzione è quella di usare il saharspec gem e la sua negazione del matcher dont.

Ecco un estratto dal README del progetto:

Altro (sperimentale) tentativo di sbarazzarsi di define_negated_matcher. dont non è grammaticalmente corretto al 100%, ma abbastanza breve e leggibile. Semplicemente nega il matcher allegato.

# before 
RSpec.define_negated_matcher :not_change, :change 

it { expect { code }.to do_stuff.and not_change(obj, :attr) } 

# after: no `define_negated_matcher` needed 
require 'saharspec/matchers/dont' 

it { expect { code }.to do_stuff.and dont.change(obj, :attr) } 

Così si può scrivere la tua aspettativa senza creare un matcher negata come questo:

expect { 
    # running migration and user reload here 
}.to dont.change(user, :avatar_url).from(sample_avatar_url).and 
    dont.change(user, :old_avatar).from(nil)