转载

[RSpec] 進階測試系列概念 - Part 5 Stubbing

double 可以讓我們輕易地閃掉準備「協作者」的痛苦。但是有時候,我們還是可能被「協作者」本身的內部邏輯改變整到。比如說,這裡是一個「建議」Suggestion 表單:

require 'rails_helper'  RSpec.describe SuggestionsController, type: :controller do    describe "POST create" do      context "when suggestion is invalid" do        it "render new" do          post :create, :suggestion => { :title => "", :description => "" }          expect(response).to render_template :new       end     end   end end
class Suggestion < ActiveRecord::Base    validates :title, presence: true end
class SuggestionsController    def create     @suggestion = Suggestion.new(suggestion_params)     if @suggestion.save       redirect_to root_path     else       render :new     end   end    protected    def suggestion_params     params.require(:suggestion).permit(:title, :description)   end  end

如果物件非法的話,要 render new 這個 action。正常來說,這樣的 controller 測試,應該會通過。

但是有時候 controller 程式碼沒有動,但 model 程式碼內部動了,比如說在這個例子,可能多加了新的欄位,或者是新增了其他的驗證方式,導致這個 controller 測試要因為 suggestion 內部本身的邏輯要修改。

這樣真的很討厭。

重寫測試

其實這裡我們根本不應該塞「例子」進去,這樣 suggestion 內部邏輯一旦改變,我們的 controller test 就要改個沒完。我們真正應該要做的是:

  • 準備一個「一定儲存失敗的替身」
  • 然後在 controller 讓 @suggestion.save 鐵定失敗
  • 因為我們要驗證的是 「render :new」

所以我們可以把測試改寫成這樣

require 'rails_helper'  RSpec.describe SuggestionsController, type: :controller do    describe "POST create" do      context "when suggestion is invalid" do        it "render new" do          invalid_suggestion = double(:save => false)          allow(Suggestion).to receive(:new).and_return(invalid_suggestion)          post :create, :suggestion => { :xxx => "yyy" }          expect(response).to render_template :new       end     end   end end

這樣 suggestion 內部驗證再怎麼樣變,都不會影響到這個 controller test。

原文  http://blog.xdite.net/posts/2016/06/11/rspec-advanced-concept-part-5
正文到此结束
Loading...