Domanda

Non sono stato in grado di trovare nulla per una situazione come questa. Ho un modello che ha un ambito definito così definito:

class Customer < ActiveRecord::Base
  # ...
  named_scope :active_customers, :conditions => { :active => true }
end

e sto provando a cancellarlo nelle specifiche del mio controller:

# spec/customers_controller_spec.rb
describe CustomersController do
  before(:each) do
    Customer.stub_chain(:active_customers).and_return(@customers = mock([Customer]))
  end

  it "should retrieve a list of all customers" do
    get :index
    response.should be_success
    Customer.should_receive(:active_customers).and_return(@customers)
  end
end

Questo non funziona e non funziona, dicendo che il Cliente si aspetta che active_customers lo abbia ricevuto 0 volte. Nel mio controller effettivo per l'azione sull'indice ho @customers = Customer.active_customers . Cosa mi manca per farlo funzionare? Purtroppo, sto scoprendo che è più semplice scrivere il codice piuttosto che pensare a un test / specifica e scriverlo dal momento che so cosa sta descrivendo la specifica, ma non come dire a RSpec cosa voglio fare.

È stato utile?

Soluzione

Penso che ci sia un po 'di confusione quando si tratta di stub e aspettative del messaggio . Le aspettative dei messaggi sono fondamentalmente stub, in cui è possibile impostare la risposta predefinita desiderata, ma verificano anche che la chiamata sia effettuata dal codice in fase di test. Al contrario, gli stub sono solo risposte predefinite alle chiamate del metodo. Ma non mescolare uno stub con un'aspettativa di messaggio sullo stesso metodo e testare o succederanno cose brutte ...

Tornando alla tua domanda, ci sono due cose (o più?) che richiedono di specificare qui:

  1. Che il Controllore Clienti chiama Cliente # active_customers quando si fa un get su index . Non importa davvero cosa Customer # active_customers restituisce in questa specifica.
  2. Che il active_customers named_scope in effetti restituisce i clienti in cui il campo active è true .

Penso che tu stia provando a fare il numero 1. In tal caso, rimuovi l'intero stub e imposta semplicemente le aspettative del messaggio nel tuo test:

describe CustomersController do
  it "should be successful and call Customer#active_customers" do
    Customer.should_receive(:active_customers)
    get :index
    response.should be_success
  end
end

Nelle specifiche sopra non stai testando cosa restituisce. Va bene poiché questo è lo scopo della specifica (anche se la tua specifica è troppo vicina all'implementazione rispetto al comportamento, ma questo è un argomento diverso). Se vuoi che la chiamata a active_customers restituisca qualcosa in particolare, vai avanti e aggiungi .and_returns (@whatever) alle aspettative di quel messaggio. L'altra parte della storia è testare che active_customers funziona come previsto (ad es .: una specifica del modello che effettua l'effettiva chiamata al DB).

Altri suggerimenti

Dovresti avere l'array intorno alla simulazione se vuoi provare a ricevere indietro un array di record del cliente in questo modo:

Customer.stub_chain(:active_customers).and_return(@customers = [mock(Customer)])

stub_chain ha funzionato al meglio per me.

Ho un controller che chiama

ExerciseLog.this_user(current_user).past.all

E sono in grado di stubare in questo modo

ExerciseLog.stub_chain(:this_user,:past).and_return(@exercise_logs = [mock(ExerciseLog),mock(ExerciseLog)])
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top