Domanda

Mi dispiace, ma questo inizia a sentirmi a calci in testa. Sono completamente sconcertato da RSpec. Ho visto video dopo video, letto tutorial dopo tutorial, e sono ancora bloccato sul punto di partenza.

=== ecco cosa sto lavorando

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

=== Errori

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

=== ecco l'azione del mio controller

  def bid

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

  end

=== ecco il mio test

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 / albero / master / spec / spec_helper.rb

È molto scoraggiante svegliarsi per il lavoro alle 3 del mattino e non fare nulla per il giorno. Per favore, capisci.

È stato utile?

Soluzione

Hai un paio di cose al contrario prima (: ognuna). Visto che l'esempio sta specificando che il post dovrebbe aumentare il conteggio di 1, hai a che fare con record reali e non c'è motivo di stubbare nulla. Inoltre, a questo punto, poiché esiste un solo esempio, non vi è alcun motivo per avere un blocco prima. Lo farei così:

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

Una cosa che consiglierei è creare queste cose MOLTO granularmente per ora fino a quando non le capirai meglio. Inizia con le aspettative (il post dovrebbe cambiare il conteggio delle offerte), esegui la specifica e lascia che il messaggio di errore ti guidi nell'aggiungere qualsiasi altra cosa di cui hai bisogno nella specifica o nel codice.

Altri suggerimenti

Jesse,

Passerà comunque se commenterai le 2 ° due righe di prima (: ognuna), che non hanno alcun impatto sulla "quot", dovrebbe creare una nuova offerta " esempio.

La parola chiave lambda crea un blocco arbitrario di codice che non viene eseguito quando lo si definisce, ma in realtà è un oggetto che è possibile assegnare a una variabile ed eseguire in seguito:

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

A questo punto quel codice non viene eseguito, ma possiamo fare riferimento ad esso con la variabile 'the_post'. Ora possiamo inviarlo "should", seguito da "change ...", in questo modo:

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

Quando viene eseguita questa riga, accadono alcune cose. Il materiale a destra di "should" viene valutato per primo, inizializzando un oggetto matcher rspec con alcune istruzioni. Quel matcher è l'argomento di "dovrebbe" - l'equivalente di questo:

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

Il metodo 'should' è chiamato su the_post, che è il blocco di codice (che non è stato ancora eseguito). Sotto il cofano, il metodo 'should' passa self (the_post) al matcher, quindi il matcher ora ha tutto il necessario per valutare l'esempio.

Il matcher chiama Bid.count e registra il valore. Quindi esegue il blocco (the_post), quindi chiama Bid.count una seconda volta e lo confronta con il valore registrato in precedenza. In questo caso, poiché stiamo cercando Bid.count per cambiare di 1 (il positivo è implicito qui - aumenta di 1), se è quello che succede il matcher rimane in silenzio e l'esempio passa.

Se i valori sono uguali o differiscono di un valore diverso da 1, l'esempio fallirà. Puoi vedere che funziona se cambi l'aspettativa in da (2) anziché da (1).

HTH, David

EDIT: non dovresti aspettarti che Bid.count aumenti quando usi un oggetto simulato. Ho dimenticato il mantra: caffeina prima del codice.

Per ora basta commentare le righe, quindi l'originale è ancora lì.

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

Prova a scrivere le specifiche più piccole possibili, scrivi le tue impostazioni in modo da rendere ovvio ciò che dovresti verificare in quella specifica. Ad esempio, il modo in cui ho cambiato il tuo da esso " dovrebbe funzionare " a esso " dovrebbe creare una nuova offerta " . Se c'è di più in quel controller, scrivi una nuova specifica per ogni piccola funzionalità.

Se finisci per aver bisogno di utenti finti, ci sono alcuni aiutanti per l'autenticazione restful che lo rendono più facile. Per prima cosa crea un dispositivo utente in RAILS_ROOT / spec / fixtures / users.yml , in questo modo:

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"

Quindi nelle tue specifiche sarai in grado di scrivere quanto segue e avere il tuo metodo current_user e tutte le altre parti di restul_authentication comportarsi come ci si aspetterebbe da loro in fase di esecuzione.

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

Come esempio di alcune altre specifiche, potrei aggiungere altri due esempi:

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

Anche se non capisco bene cosa stia succedendo. (con mozziconi e lambda) ....

per

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

I seguenti passi !!

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top