質問

申し訳ありませんが、これは頭の中で自分を蹴りたくなり始めています。私はRSpecに完全に困惑しています。次から次へとビデオを見て、チュートリアルごとにチュートリアルを読んで、それでも私は四角に止まっています。

===これが私が取り組んでいるものです

http://github.com/fudgestudios/bort/tree/master

===エラー

F

1)
NoMethodError in 'bidding on an item should work'
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.new_record?
spec/controllers/auction_controller_spec.rb:16:
spec/controllers/auction_controller_spec.rb:6:

Finished in 0.067139 seconds

1 example, 1 failure

===ここに私のコントローラーアクションがあります

  def bid

      @bid = Bid.new(params[:bid])
      @bid.save

  end

===ここに私のテストがあります

require File.dirname(__FILE__) + '/../spec_helper'
include ApplicationHelper
include UsersHelper
include AuthenticatedTestHelper

describe "bidding on an item" do
  controller_name :items

    before(:each) do
      @user = mock_user
      stub!(:current_user).and_return(@user)
    end

  it "should work" do
    post 'bid', :bid => { :auction_id => 1, :user_id => @user.id, :point => 1 }
    assigns[:bid].should be_new_record
  end

end

=== spec_helper

http://github.com/fudgestudios/ bort / tree / master / spec / spec_helper.rb

午前3時に仕事のために目を覚まし、その日に何も達成しないのは非常に残念です。理解してください。

役に立ちましたか?

解決

before(:each)には後方にいくつかのものがあります。例として見ると、投稿でカウントを1増やす必要があると指定しているため、実際のレコードを処理しているため、スタブ化する理由はまったくありません。また、この時点では、例は1つしかないため、beforeブロックを作成する理由はありません。このようにします:

describe ItemsController, "bidding on an item" do
  fixtures :users

  it "should create a new Bid" do
    login_as :quentin
    lambda do
      post 'bid', :bid => { :auction_id => 1, :user_id => @user.id, :point => 1 }
    end.should change(Bid, :count).by(1)
  end

end

私がお勧めすることの1つは、これらをよりよく理解するまで、今のところ非常に細かく作成することです。期待から始めて(投稿は入札カウントを変更する必要があります)、仕様を実行し、失敗メッセージにガイドまたは仕様またはコードに必要なものを追加してもらいます。

他のヒント

ジェシー、

before(:each)の2番目の2行をコメントアウトした場合でも、「新しい入札を作成する必要があります」に影響はありません。例。

lambdaキーワードは、定義時に実行されないが、実際には変数に割り当てて後で実行できるオブジェクトである任意のコードブロックを作成します。

the_post = lambda do
  post 'bid', :bid => { :auction_id => 1, :user_id => @user.id, :point => 1 }
end

この時点では、コードは実行されませんが、「the_post」変数で参照できます。次のように、「should」に続いて「change ...」を送信できます。

the_post.should change(Bid, :count).by(1)

この行が実行されると、いくつかのことが起こります。 'should'の右側のマテリアルが最初に評価され、いくつかの指示でrspecマッチャーオブジェクトが初期化されます。そのマッチャーは 'should'の引数です-これと同等:

matcher = change(Bid, :count).by(1)
the_post.should(matcher)

「should」メソッドは、コードブロック(まだ実行されていない)であるthe_postで呼び出されます。内部では、 'should'メソッドはself(the_post)をマッチャーに渡します。そのため、マッチャーは例の評価に必要なものをすべて備えています。

マッチャーはBid.countを呼び出し、値を記録します。次に、ブロック(the_post)を実行し、Bid.countを2回呼び出して、以前に記録した値と比較します。この場合、Bid.countが1だけ変化することを探しているため(ここでは正の値が暗黙的-1ずつ増加します)、それが起こると、マッチャーはサイレントのままで、例はパスします。

値が同じ場合、または1以外の値が異なる場合、この例は失敗します。期待をby(1)ではなくby(2)に変更すると、その動作を確認できます。

HTH、 デビッド

編集:モックオブジェクトを使用するときにBid.countが増加することを期待しないでください。私が忘れていたマントラ:コードの前にカフェイン。

今は行をコメントアウトするだけなので、オリジナルはまだそこにあります。

require File.dirname(__FILE__) + '/../spec_helper'
include ApplicationHelper
include UsersHelper
include AuthenticatedTestHelper

describe "POST to bid_controller" do
  controller_name :items

  before(:each) do
        #@bid = mock_model(Bid)           # create a new mock model so we can verify the appropriate things
        #Bid.stub!(:new).and_return(@bid) # stub the new class method on Bid to return our mock rather than a new ActiveRecord object.
                                         # this separates our controller spec entirely from the database.
  end

  it "should create a new Bid" do
    lambda do
        post 'bid', :bid => { :auction_id => 1, :user_id => @user.id, :point => 1 }
    end.should change(Bid, :count).by(1)
  end

    # ... more specs
end

可能な限り小さな仕様を記述し、その仕様で検証すべき内容が明確になるように設定を記述してください。たとえば、 it" should work" から it" should a new Bid" に変更した場合。そのコントローラーにもっとあるなら、新しい仕様を書く 機能の小さな部分ごとに。

最終的に模擬ユーザーが必要になった場合、restful_authenticationのヘルパーを使用して簡単に実行できます。最初にユーザーフィクスチャを作成します RAILS_ROOT / spec / fixtures / users.yml 、このように:

quentin:
  login: quentin
  email: quentin@example.com
  salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
  crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
  created_at: <%= 5.days.ago.to_s :db %>
  activation_code: 8f24789ae988411ccf33ab0c30fe9106fab32e9b 
  activated_at: <%= 5.days.ago.to_s :db %> 
  name: "Quentin"

次に、仕様で次を記述し、 current_user メソッドとrestul_authenticationの他のすべての部分を使用できます。 実行時に期待どおりに動作します。

login_as :quentin
# .... the rest of your spec

さらにいくつかの仕様の例として、さらに2つの例として追加します。

def do_post
    # extracting the method under test, so I don't repeat myself
    post 'bid', :bid => { :auction_id => 1, :user_id => @user.id, :point => 1 }
end

it "should create a new Bid" do
    lambda do
    do_post
    end.should change(Bid, :count).by(1)
end

it "should assign the Bid to the proper auction" do
    @bid.should_receive(:auction_id=).with(1) # test this, I believe doing  Bid.new(params[:bid]) sets the id directly not sets the model
    do_post
end

it "should assign the Bid the proper points" do
    @bid.should_receive(:point=).with(1)
    do_post
end

何が起こっているのかよくわかりませんが。 (スタブとラムダを使用)....

for

def bid
  @bid = Bid.new params[:bid]
  @bid.save
end

次の合格!!

require File.dirname(__FILE__) + '/../spec_helper'
include ApplicationHelper
include UsersHelper
include AuthenticatedTestHelper

describe "bidding on an item" do
  controller_name :items
  fixtures :users

  before(:each) do
    @user = login_as :quentin
    @bid = mock_model(Bid)           # create a new mock model so we can verify the appropriate things
    @bid.stub!(:new).and_return(@bid) # stub the new class method on Bid to return our mock rather than a new ActiveRecord object.
    #Bid.stub!(:save).and_return(true)# this separates our controller spec entirely from the database.
  end

  it "should create a new Bid" do
    lambda do
      post 'bid', :bid => { :auction_id => 1, :user_id => @user.id, :point => 1 }
    end.should change(Bid, :count).by(1)
  end

end
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top