2010-09-01 10 views
35

Soy nuevo para simular objetos, y estoy tratando de aprender a usarlos en RSpec. ¿Puede alguien publicar un ejemplo (un ejemplo de hello RSpec Mock object world type), o un enlace (o cualquier otra referencia) sobre cómo usar el objeto RSpec simulado API?Ejemplo de objeto falso RSpec

Respuesta

62

He aquí un ejemplo de una simple maqueta que hice para una prueba del controlador en una aplicación de rieles:

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 

En este caso, me estoy burlando de los modelos tipo de página Página & (objetos), así como apagando algunos de los métodos que llamo

Esto me da la posibilidad de ejecutar un análisis de esta manera:

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

sé esta respuesta es más carriles específicos, pero espero que le ayuda un poco.


Editar

Ok, así que aquí es un ejemplo del mundo hola ...

Dado el siguiente script (hello.rb):

class Hello 
    def say 
    "hello world" 
    end 
end 

Podemos crear la siguiente especificación (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

gracias por el ejemplo, se quieren ofrecerlas. ayudó – agentbanks217

+11

Está configurando un objeto simulado de la clase que se supone que debe especificar/probar, lo que significa que no está ejercitando la clase que está siendo devuelta. Inútil. La burla está destinada a ayudarlo a rodear la clase/sistema bajo prueba con objetos que se hacen pasar por un entorno del mundo real, aunque más simple/controlado/autónomo. Es un anti-patrón usar Mocking para verificar el funcionamiento interno de la clase que se está desarrollando. –

+0

Además, esta respuesta no está actualizada. Consulte [la respuesta de tokhi a continuación] (https://stackoverflow.com/a/39573538/634576) para saber cómo escribir un objeto falso real y [mío] (https://stackoverflow.com/a/39186152/634576) cómo hacer burlas parciales en RSpec actual. –

5

No tengo suficientes puntos para publicar un comentario en una respuesta, pero quería decir que la respuesta aceptada también me ayudó a tratar de encontrar la forma de un tope en un valor aleatorio.

que tenía que ser capaz de código auxiliar valor de la instancia de un objeto que se asigna al azar, por ejemplo:

class ClumsyPlayer < Player do 

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

Luego, en mi especificación que tenía un problema en encontrar la manera de muñón de la salud aleatoria del jugador torpe para poner a prueba que cuando obtienen una curación, obtienen el impulso adecuado para su salud.

El truco era:

@player.stub!(health_boost: 5) 

Para que stub! fue la clave, que había estado usando sólo stub y todavía estaba recibiendo pases rspec azar y fracasos.

así que gracias Brian

0

actual (3.x) RSpec ofrece ambos objetos puros falsos (como en tokhi's answer) y burlona parcial (burlarse de llamadas a un objeto existente). Aquí hay un ejemplo de burla parcial. Utiliza expect y receive para simular una llamada de Order a CreditCardService, de modo que la prueba solo se transmita si la llamada se realiza sin tener que realizarla.

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 

En este ejemplo la maqueta está en el valor de retorno de CreditCardService.instance, que es presumiblemente un singleton.

with es opcional; sin él, cualquier llamada al refund satisfaría las expectativas. Se podría dar un valor de retorno con and_return; en este ejemplo, no se usa, por lo que la llamada devuelve nil.


En este ejemplo se utiliza la corriente (expect .to receive) sintaxis burlarse de RSpec, que funciona con cualquier objeto. La respuesta aceptada usa el antiguo método rspec-rails mock_model, que era específico de los modelos ActiveModel y se movía fuera de rspec-rails a otra gema.

4

mock está en desuso en función de este github pull.

Ahora, en lugar podemos utilizar double - más 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 
Cuestiones relacionadas