2017-03-03 38 views
0

一個模塊的方法的請求我在Rails API下列模塊:RSpec的測試依賴於返回的隨機數

module SpeedCalculator 

    def self.adjustment 
    Random.rand(0..0.3) 
    end 

    def self.calculate_adjustment(track, car_speed) 
    case track.surface_type 
     when "asphalt" 
     car_speed - (car_speed * self.adjustment).ceil 
     when "gravel" 
     car_speed - (car_speed * self.adjustment).ceil 
     when "snow" 
     car_speed - (car_speed * self.adjustment).ceil 
     else 
     car_speed 
    end 
    end 
end 

我可以成功地測試該調整方法是這樣的:

require 'rails_helper' 

RSpec.describe SpeedCalculator do 
    include SpeedCalculator 

    it "uses an adjustment value between 0 and 0.3" do 
    expect(SpeedCalculator.adjustment).to be >= 0 
    expect(SpeedCalculator.adjustment).to be <= 0.3 
    end 
end 

有可能作出這樣的API請求:

本地主機:3000/API/V1 /汽車/保時捷911軌=摩納哥

您要求系統計算給定軌道上給定汽車的速度。

所以我需要編寫一個請求規範,對於給定的汽車和軌道,返回正確的值。但是如果calculate_adjustment總是應用一個隨機數,我該怎麼做呢?

我相信,我需要創建一個self.adjustment模擬/存根,因此測試將是這樣的:

it "calculates max_speed_on_track when a valid track name is provided" do 
     Car.create!(name:'Subaru Impreza', max_speed:'120', speed_unit:'km/h') 
     Track.create(name:'Monaco') 

     # here create a dummy version of adjustment 
     # that always returns a fixed value, rather than a random value 
     # and somehow use that dummy for the request? 
     # Since x below needs to be a known value for the test to work. 

     get api_v1_car_path(id: 'porsche-911', track: 'monaco')  
     expect(response).to have_http_status(200) 
     expect(response.body).to include_json(car: {max_speed_on_track: x})  
    end 

回答

2

我該怎麼做,當calculate_adjustment總是應用隨機數?

我相信,我需要創建一個模擬/存根self.adjustment

究竟!你想要測試的最後一件事是隨機行爲(和隨機失敗)。你想要可重現的結果。所以是的,嘲笑你的RNG。

簡單事情會是這樣:

expect(Random).to receive(:rand).with(0..0.3).and_return(0.1234) 
# or better 
expect(SpeedCalculator).to receive(:adjustment).and_return(0.1234) 

# then proceed with your test 
get api_v1_car_path(id: 'porsche-911', track: 'monaco') 
... 

進一步改善這裏是不使用控制器的規格來測試業務邏輯。將您的業務邏輯封裝在一個對象中並測試該對象(您可以在其中最大限度地使用依賴注入技術)。而你的控制器會變成這樣的:

class CarsController 
    def show 
    calculator = MaxSpeedCalculator.new(params[:id], params[:track]) 
    render json: calculator.call 
    end 
end 
+0

但這是我的問題 - 我該如何嘲笑它? – rmcsharry

+0

我打算編寫單獨的測試來測試模塊中的方法。 REQUEST規範將測試返回正確的json,就是這樣。我只是不知道如何讓該請求使用模擬調整方法而不是模塊中的隨機調整方法。另外,在你的控制器例子中,什麼是「呼叫」正確呼叫? – rmcsharry

+0

在我的例子中,'call'是'MaxSpeedCalculator'對象的一個​​方法,它返回一個散列。 –