RSpec + FactoryGirl должен_принимать сбой - PullRequest
0 голосов
/ 16 ноября 2011

Я не могу понять, почему этот тест RSpec не проходит.Любой совет?Я новичок в FactoryGirl, RSpec и TDD в целом.

Контроллер:

def update
  @vendor = current_user.vendors.find(params[:id])

  if @vendor.update_attributes(params[:vendor])
    redirect_to vendor_path(@vendor)
  else
    render 'edit'
  end
end

Тест:

require 'spec_helper'

describe VendorsController do
  login_user

  before :each do
    @user = subject.current_user
    @vendor = FactoryGirl.create(:vendor, :user => @user)
  end

  [...]

  describe 'POST update' do
    def do_update
      post :update, :id => @vendor.id, :vendor => FactoryGirl.attributes_for(:vendor)
    end

    [...]

    it 'should update a given vendor' do
      do_update
      @vendor.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
    end
  end
end

Фабрика:

FactoryGirl.define do
  factory :vendor do
    name 'Widget Vendor'
    user
  end
end

Ошибка:

Failures:

  1) VendorsController POST update should update a given vendor
     Failure/Error: @vendor.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
       (#<Vendor:0x007faeb75e77d0>).update_attributes({:name=>"Widget Vendor"})
           expected: 1 time
           received: 0 times
     # ./spec/controllers/vendors_controller_spec.rb:108:in `block (3 levels) in <top (required)>'

Обновление:

Я немного ближе, сейчас.Я изменил тест на следующее:

it 'should update a given vendor' do
  Vendor.any_instance.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
  do_update
end

И новая ошибка:

Failures:

  1) VendorsController POST update should update a given vendor
     Failure/Error: post :update, :id => @vendor.id, :vendor => FactoryGirl.attributes_for(:vendor)
       #<Vendor:0x007ff30d765900> received :update_attributes with unexpected arguments
         expected: ({:name=>"Widget Vendor"})
              got: ({"name"=>"Widget Vendor"})
     # ./app/controllers/vendors_controller.rb:33:in `update'
     # ./spec/controllers/vendors_controller_spec.rb:98:in `do_update'
     # ./spec/controllers/vendors_controller_spec.rb:108:in `block (3 levels) in <top (required)>'

Ответ ...?

Ну, это сработало.Должен быть лучший способ сделать это, хотя:

Vendor.any_instance.should_receive(:update_attributes).with(JSON.parse(FactoryGirl.attributes_for(:vendor).to_json)).and_return(true)

Ответы [ 3 ]

2 голосов
/ 16 ноября 2011

Я думаю, что вы делаете это неправильно.

Объект @vendor в спецификации - это еще один объект в вашем контроллере, поэтому он не получает метод "update_attributes".

Вы можетепопробуйте это (rspec 2.5+, вероятно):

Vendor.any_instance.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))

Или вы можете проверить, изменились ли атрибуты объекта:

expect{
  do_update
}.to change(...)
1 голос
/ 16 ноября 2011

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

it 'should update a given vendor' do
  @vendor.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor))
  do_update
end
0 голосов
/ 02 августа 2012

Вы можете использовать метод Hash stringify keys в rails:

Vendor.any_instance.should_receive(:update_attributes).with(FactoryGirl.attributes_for(:vendor).stringify_keys)
...