2016-03-08 3 views
1

У меня есть объект что-то вроде службы:Как проверить, получает ли класс сообщение в RSpec?

class SecurityQueryService 
    class Contract::NotFound < StandardError; end 

    attr_reader :ticker_name, :contract_type, :contract 

    def initialize(user, params) 
    @user   = user 
    @ticker_name = params[:ticker_name].upcase 
    @contract_type = params[:type] 
    end 

    def call 
    find_contract 
    end 

    private 

    def find_contract 
    @contract ||= contract_klass.find_by(ticker: ticker_name) 
    fail(
     Contract::NotFound, 
     "Cannot find contract with ticker_name #{ticker_name}" 
    ) if @contract.nil? 
    end 

    def contract_klass 
    return EquityContract if contract_type.nil? 
    "#{contract_type.strip.capitalize}Contract".constantize 
    end 

end 

И у меня есть следующие связанные спецификации:

require 'spec_helper' 

describe SecurityQueryService do 
    let(:user) { create(:customer) } 
    let!(:equity_contract) { create(:equity_contract) } 

    describe "#call" do 
    describe "#find_contract" do 
     it "returns contract based on contract type." do 
     service = SecurityQueryService.new(user, { 
      type: 'equity', 
      ticker_name: equity_contract.ticker 
     }) 
     service.call 
     expect(EquityContract).to receive(:find_by) 
     end  
    end 
    end 

end 

Я хочу, чтобы убедиться, что EquityContract получает find_by сообщение всякий раз, когда я называю #call.

В тот момент, когда я бегу спецификации я получаю:

Failure/Error: expect(EquityContract).to receive(:find_by) 
    (EquityContract(id: integer, ticker: string, name: string, country: string, currency: string, instrument_type: string, bloomberg_ticker: string, benchmark_index: string, skip_valuation: boolean, isin: string, currency_factor: decimal, daily_update: boolean, id_bb_unique: string, image: string, domain: string) (class)).find_by(*(any args)) 
     expected: 1 time with any arguments 
     received: 0 times with any arguments 

Как я могу проверить это поведение?

+1

Переместить ожидание до 'service.call'. –

+0

@DaveSchweisguth вы можете добавить его в качестве ответа, чтобы я мог его одобрить? благодаря –

ответ

1

Вам необходимо настроить макет перед вызовом метода. RSpec предоставляет два способа сделать это:

  1. Перемещение ожидания перед тем service.call:

    describe "#find_contract" do 
        it "returns contract based on contract type." do 
        service = SecurityQueryService.new(user, 
         type: 'equity', 
         ticker_name: equity_contract.ticker 
        ) 
        expect(EquityContract).to receive(:find_by) 
        service.call 
        end  
    end 
    
  2. Настройка метода как шпиона по allow ИНГ метод, который можно назвать, то ожидать, что она есть был вызван после факта:

    describe "#find_contract" do 
        it "returns contract based on contract type." do 
        service = SecurityQueryService.new(user, 
         type: 'equity', 
         ticker_name: equity_contract.ticker 
        ) 
        allow(EquityContract).to receive(:find_by) 
        service.call 
        expect(EquityContract).to have_received(:find_by) 
        end  
    end 
    

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