Подтвердить что ты не робот

Пример RSock Mock Object

Я новичок в подделке объектов, и я пытаюсь научиться их использовать в RSpec. Может кто-нибудь, пожалуйста, отправьте пример (привет приветственный пример типа объекта MPpec Mock) или ссылку (или любую другую ссылку) о том, как использовать API-интерфейс макетного объекта RSpec?

4b9b3361

Ответ 1

Вот пример простого макета, который я сделал для теста контроллера в приложении rails:

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

В этом случае я издеваюсь над страницами и типами страниц (Objects), а также излагаю несколько методов, которые я вызываю.

Это дает мне возможность запускать тесты следующим образом:

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

Я знаю, что этот ответ больше специфичен для рельсов, но я надеюсь, что это поможет вам немного.


Edit

Итак, вот пример мира привет...

Учитывая следующее script (hello.rb):

class Hello
  def say
    "hello world"
  end
end

Мы можем создать следующую спецификацию (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

Ответ 2

У меня недостаточно баллов, чтобы опубликовать комментарий к ответу, но я хотел сказать, что принятый ответ также помог мне разобраться, как заглушить случайное значение.

Мне нужно было иметь возможность заглушить значение экземпляра объекта, которое случайным образом назначается, например:

class ClumsyPlayer < Player do

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

Тогда в моей спецификации у меня возникла проблема с выяснением того, как заглушить неуклюжее случайное здоровье игрока, чтобы проверить, что, когда они получат исцеление, они получают правильный импульс к своему здоровью.

Трюк был:

@player.stub!(health_boost: 5)

Таким образом, что stub! был ключом, я просто использовал stub и все еще получал случайные пропуски rspec и отказы.

Так что спасибо Брайан

Ответ 3

mock устарел на основе этого github pull.

Теперь вместо этого мы можем использовать double - больше здесь...

 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

Ответ 4

Current (3.x) RSpec предоставляет как чистые макетные объекты (как в tokhi answer), так и частичные издевательства (насмешливые звонки на существующий объект). Вот пример частичной насмешки. Он использует expect и receive, чтобы высмеять вызов Order на CreditCardService, так что тест проходит только в том случае, если вызов выполняется без фактического его выполнения.

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

В этом примере макет находится на возвращаемом значении CreditCardService.instance, который предположительно является одиночным.

with не является обязательным; без него любой вызов refund удовлетворяет ожиданию. Возвращаемое значение может быть задано с помощью and_return; в этом примере он не используется, поэтому вызов возвращает nil.


В этом примере используется синхронный синтаксис RSpec current (expect .to receive), который работает с любым объектом. В принятом ответе используется старый метод rspec-rails mock_model, который был специфичен для моделей ActiveModel и был перемещен из rspec-rails на другой камень.