2017-03-03 6 views
0

返すモジュール方式に依存して要求テスト:RSpecのは、私はRailsのAPIで、次のモジュールを持っている乱数

:私は成功した調整方法は次のように動作することをテストすることができ

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リクエストを行うことが可能である:

はlocalhost:3000/API/V1 /車/ポルシェ-911トラック=モナコ

? 10

ここでは、指定されたトラック上の特定の車の速度を計算するようにシステムに依頼しています。

私は、特定の車とトラックに対して、正しい値が返されるという要求仕様を書く必要があります。しかし、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が返されたことをテストすることです。それだけです。私はちょうどそのリクエストが、モジュール内のランダムなものではなく嘲笑された調整方法を使用するようにすることができるかどうか分かりません。また、あなたのコントローラーの例では、 'call'は正確に何を呼び出していますか?私の例では – rmcsharry

+0

、 'call'は' MaxSpeedCalculator'オブジェクトのメソッドで、ハッシュを返します。 –

関連する問題