2010-09-01 3 views
35

Sono un neofita degli oggetti di simulazione e sto cercando di imparare come usarli in RSpec. Qualcuno può per piacere postare un esempio (un esempio di tipo di mondo di oggetto RSpec Mock ciao), o un link (o qualsiasi altro riferimento) su come usare l'API dell'oggetto mock RSpec?Esempio di oggetto simulato RSpec

risposta

62

Ecco un esempio di una semplice finta che ho fatto per un test di controllo in un'applicazione rotaie:

before(:each) do 
    @page = mock_model(Page) 
    @page.stub!(:path) 
    @page.stub!(:find_by_id) 
    @page_type = mock_model(PageType) 
    @page_type.stub!(:name) 
    @page.stub!(:page_type).and_return(@page_type) 
end 

In questo caso, sto beffardo i modelli pagetype Pagina & (oggetti) e spegnendo alcuni dei metodi che chiamo.

Questo mi dà la possibilità di eseguire un test come questo:

it "should be successful" do 
    Page.should_receive(:find_by_id).and_return(@page) 
    get 'show', :id => 1 
    response.should be_success 
end 

So che questa risposta è più rotaie specifica, ma spero che ti aiuta un po '.


Modifica

Ok, ecco un esempio del mondo ciao ...

Dato il seguente script (hello.rb):

class Hello 
    def say 
    "hello world" 
    end 
end 

Possiamo creare la seguente specifica (hello_spec.rb):

require 'rubygems' 
require 'spec' 

require File.dirname(__FILE__) + '/hello.rb' 

describe Hello do 
    context "saying hello" do 
    before(:each) do 
     @hello = mock(Hello) 
     @hello.stub!(:say).and_return("hello world") 
    end 

    it "#say should return hello world" do 
     @hello.should_receive(:say).and_return("hello world") 
     answer = @hello.say 
     answer.should match("hello world") 
    end 
    end 
end 
+0

grazie per l'esempio, deff. aiutato – agentbanks217

+11

Stai configurando un oggetto fittizio della classe che dovresti speculare/test, il che significa che non stai esercitando la classe in fase di sviluppo. Inutile. Mocking ha lo scopo di aiutarti a circondare la classe/il sistema in prova con oggetti che si fingono credibilmente come un ambiente reale, anche se più semplice/controllato/autonomo. È un anti-pattern per usare Mocking per controllare i meccanismi interni della classe che si sta sviluppando. –

+0

Inoltre, questa risposta non è aggiornata. Vedi [tokhi's answer below] (https://stackoverflow.com/a/39573538/634576) su come scrivere un oggetto mock puro e [mio] (https://stackoverflow.com/a/39186152/634576) per come fare il mocking parziale in RSpec corrente. –

5

Non ho abbastanza punti per inviare un commento ad una risposta, ma volevo dire che la risposta accettata mi ha aiutato anche a cercare di capire come stub in un valore casuale.

avevo bisogno di essere in grado di stub valore di istanza di un oggetto che viene assegnato in modo casuale ad esempio:

class ClumsyPlayer < Player do 

    def initialize(name, health = 100) 
    super(name, health) 
    @health_boost = rand(1..10) 
    end 
end 

Poi nella mia spec Ho avuto un problema sul capire come stub la salute casuale del giocatore maldestro di testare che quando ottengono una guarigione, ottengono la spinta giusta per la loro salute.

Il trucco era:

@player.stub!(health_boost: 5) 

Quindi stub! è stata la chiave, mi era stato appena usando stub ed ero ancora ricevendo passaggi RSpec casuali e fallimenti.

Quindi grazie Brian

0

corrente (3.x) RSpec fornisce entrambi gli oggetti puri finte (come in tokhi's answer) e beffardo parziale (beffardo chiamate a un oggetto esistente). Ecco un esempio di derisione parziale. Utilizza expect e receive per simulare una chiamata di Order a CreditCardService, in modo che il test passi solo se la chiamata viene effettuata senza doverla effettivamente eseguire.

class Order 
    def cancel 
    CreditCardService.instance.refund transaction_id 
    end 
end 

describe Order do 
    describe '#cancel' do 
    it "refunds the money" do 
     order = Order.new 
     order.transaction_id = "transaction_id" 
     expect(CreditCardService.instance).to receive(:refund).with("transaction_id") 
     order.cancel 
    end 
    end 
end 

In questo esempio il mock è il valore restituito CreditCardService.instance, che è presumibilmente un singoletto.

with è facoltativo; senza di essa, qualsiasi chiamata a refund soddisferebbe le aspettative. Un valore di ritorno può essere dato con and_return; in questo esempio non viene utilizzato, quindi la chiamata restituisce nil.


Questo esempio utilizza corrente (expect .to receive) sintassi beffardo di RSpec, che funziona con qualsiasi oggetto. La risposta accettata utilizza il vecchio metodo rspec-rails mock_model, che era specifico per i modelli ActiveModel ed è stato spostato da rspec-rails in un'altra gemma.

4

mock è deprecato basato su questo github pull.

Ora invece possiamo usare double - più here...

before(:each) do 
    @page = double("Page") 
    end 

    it "page should return hello world" do 
    allow(@page).to receive(:say).and_return("hello world") 
    answer = @page.say 
    expect(answer).to eq("hello world") 
    end