2015-04-01 2 views
31

Я хочу проверить множество изменений в модели при отправке формы в спецификацию функции. Например, я хочу убедиться, что имя пользователя было изменено с X на Y и что зашифрованный пароль был изменен на любое значение.RSpec: ожидайте изменения нескольких

Я знаю, что есть некоторые вопросы об этом, но я не нашел подходящего ответа для меня. Самый точный ответ кажется совпадением ChangeMultiple Майклом Джонстоном здесь: Is it possible for RSpec to expect change in two tables?. Его недостатком является то, что только проверка на явные изменения от известных значений до известных значений.

Я создал некоторый псевдокод, как я думаю, что лучше согласовани может выглядеть следующим образом:

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 
) 

Я также создал основной скелет ChangeMultiple согласовани так:

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 

Но теперь Я уже получаю эту ошибку:

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/[email protected]/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `load' 
# /Users/josh/.rvm/gems/[email protected]/gems/activesupport-4.2.0/lib/active_support/dependencies.rb:268:in `block in load' 

Любая помощь при создании thi пользовательский соединитель высоко оценен.

ответ

62

В RSpec 3 вы можете установить сразу несколько условий (так что одно правило ожидания не будет нарушено). Это будет выглядеть как STH:

expect { 
    click_button 'Save' 
    @user.reload 
}.to change { @user.name }.from('donald').to('gustav') 
.and change { @user.updated_at }.by(4) 
.and change { @user.great_field }.by_at_least(23} 
.and change { @user.encrypted_password } 

Это не полное решение, хотя - насколько мои исследования пошли не простой способ сделать and_not еще. Я также не уверен в вашей последней проверке (если это неважно, зачем ее тестировать?). Естественно, вы должны иметь возможность обернуть его в пределах вашего custom matcher.

+4

, если вы хотите, чтобы ожидать, что несколько вещей * не * изменены, просто используйте '.and change {@something} .by (0)' –

+0

Можете ли вы добавить второй пример со всеми скобками? Мне трудно понять, какие методы прикованны –

4

Если вы хотите проверить, что несколько записей не были изменены, вы можете инвертировать совпадение, используя RSpec::Matchers.define_negated_matcher. Так, добавьте

RSpec::Matchers.define_negated_matcher :not_change, :change 

в верхней части файла (или на rails_helper.rb), а затем вы можете цепи с помощью and:

expect{described_class.reorder}.to not_change{ruleset.reload.position}. 
    and not_change{simple_ruleset.reload.position} 

 Смежные вопросы

  • Нет связанных вопросов^_^