2017-12-01 119 views
5

Tôi đang sử dụng Rails 5 với Rspec 3. Làm cách nào để giả lập một lớp trong phương thức Rspec của tôi? Tôi có lớp sauLàm cách nào để giả lập một lớp bằng Rspec và Rails?

require 'rails_helper' 

describe CryptoCurrencyService do 

    describe ".sell" do 

    it "basic_sell" do 
     last_buy_price = 3000 
     last_transaction = MoneyMakerTransaction.new({ 
     :transaction_type => "buy", 
     :amount_in_usd => "100", 
     :btc_price_in_usd => "#{last_buy_price}" 
     }) 
     @client = Coinbase::Wallet::Client.new(api_key: ENV['COINBASE_KEY'], api_secret: ENV['COINBASE_SECRET']) 
     sell_price = 4000 
     assert sell_price > last_buy_price * (1 + MoneyMakerThreshhold.find_buy.pct_change) 

     allow(@client).to receive(:sell_price).and_return({"base"=>"BTC", "currency"=>"USD", "amount"=>"#{sell_price}"}) 

     svc = CryptoCurrencyService.new 
     svc.sell(last_transaction) 
     last_transaction = MoneyMakerTransaction.find_latest_record 
     assert last_transaction.transaction_type, "sell" 
    end 

    end 

end 

Thay vì thực sự instantiating lớp "Coinbase :: Wallet" trong dòng

@client = Coinbase::Wallet::Client.new(api_key: ENV['COINBASE_KEY'], api_secret: ENV['COINBASE_SECRET']) 

Tôi muốn tạo taht giả sau đó tôi có thể chèn vào lớp dịch vụ của tôi mà tôi đang thử nghiệm Vì nó đang đứng ngay bây giờ, khi tôi chạy mọi thứ, lớp cơ bản thực tế đang được khởi tạo, dẫn đến lỗi thời gian chạy ...

+1

Bạn có ha da nhìn vào 'rspec-mocks' không? https://github.com/rspec/rspec-mocks –

+1

Vâng, nhưng tôi không thấy anyting mà khá phù hợp với tình hình của tôi. – Dave

Trả lời

5

rspec mocks và stubs có thể được sử dụng trên bất kỳ lớp nào. Ví dụ:

coinbase_mock = double(api_key: ENV['COINBASE_KEY'], api_secret: ENV['COINBASE_SECRET']) 
expect(Coinbase::Wallet::Client).to_receive(:new).and_return(coinbase_mock) 

sau đó bạn có thể thêm bất cứ điều gì bạn thích vào các coinbase_mock để nó quacks như lớp bạn cần ... :)

2

Bạn có thể sử dụng một Struct của Ruby như thế này:

Coinbase::Wallet::Client = Struct.new(:api_key, :api_secret) 
@client = Coinbase::Wallet::Client.new(ENV['COINBASE_KEY'], ENV['COINBASE_SECRET']) 
@client.api_key #=> whatever was in ENV['COINBASE_KEY'] 

Sau đó vượt qua đối tượng đó trong

Nếu bạn cần hành vi trên nó, bạn cũng có thể nhận được rằng như thế này:.

Coinbase::Wallet::Client = Struct.new(:api_key, :api_secret) do 
    def client_info 
    ## logic here 
    "info" 
    end 
end 

@client = Coinbase::Wallet::Client.new(ENV['COINBASE_KEY'], ENV['COINBASE_SECRET']) 
@client.client_info #=> "info" 
1

RSpec ưu tiên (từ ver. 3) phong cách sẽ là

let(:coinbase_client) { instance_double(Coinbase::Wallet::Client) } 
# validates that mocked/stubbed methods present in class definitiion 

before do 
    allow(coinbase_client).to receive(:sell_price).and_return({"base"=>"BTC", "currency"=>"USD", "amount"=>"PRICE YOU PROVIDE"}) 
end 

docs about instance_double method

khi bạn tiêm coinbase_client như một tham số xây dựng đến các lớp học của bạn mà sử dụng nó trong nội bộ

HOẶC nếu vì một số lý do bạn không thể sử dụng tiêm dependancy, bạn có thể giả sử bất kỳ phiên bản nào của Coinbase :: Wallet :: Client với

allow_any_instance_of(Coinbase::Wallet::Client).to receive(... *mock specific method*) 
Các vấn đề liên quan