How do I make fun of a class using Rspec and Rails?

I use Rails 5 with Rspec 3. How do I mock a class in my Rspec method? I have a class

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 

Instead of actually creating the "Coinbase :: Wallet" class on the line

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

I would like to create a mock taht, which could then be inserted into my service class, which I am testing. Since it stands right now when I run things, the actual base class gets the instance, which leads to a runtime error ...

  1) CryptoCurrencyService.sell basic_sell Failure/Error: payment_method = client.payment_methods()[0] Coinbase::Wallet::AuthenticationError: invalid api key 
+5
source share
3 answers

rspec mocks and stubs can be used in any class. For instance:

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

then you can add whatever you want to coinbase_mock so that it coinbase_mock down like the class you need ... :)

+5
source

You can use Ruby Struct as follows:

 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'] 

Then pass this object to.

If you need behavior on it, you can also get the following:

 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" 
+2
source

The preferred RSpec style (starting with version 3) will be

 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

while you enter coinbase_client as a construction parameter for your classes that use it inside

OR if for some reason you cannot use dependency injection, you can make fun of any instance of Coinbase :: Wallet :: Client with

 allow_any_instance_of(Coinbase::Wallet::Client).to receive(... *mock specific method*) 
+1
source

Source: https://habr.com/ru/post/1273804/


All Articles