RSpec-Rails 針對module進行unit test
本文概要:在RSpec describe中載入module必須寫成MyClass.new { include MyModule }
若使用RSpec(v3.2)對Rails進行測試,不免俗要針對各種module進行unit test,尤其是helper、service object、或是各種model及controller當中的concern。不過問題來了,要如何在測試當中載入module?小弟一直以為方式是一樣的,但殊不知,在這裡也卡關許久。
rspec-rails
這個gem library針對helper module有提供非常簡便的載入方法,我們的測試會寫成這樣:
require 'rails_helper'
RSpec.describe AppHelper, :type => :helper do
# 測試內容
end
可以注意到:type => :helper
這個敘述,等於直接載入了helper的內容,我們無需再另外考慮其他因素。
不過這裡有個陷阱,也就是並非所有module都可以這樣載入。如果我們有個service object檔案是greeter.rb
包含以下內容:
module Greeter
def hello
"hello world"
end
end
假如我們用同樣的邏輯思考,在測試檔案greeter_spec.rb
中寫:
require `rails_helper`
RSpec.describe Greeter do
it { expect(Greeter.new.hello).to eq("hello world") }
end
這樣寫會產生NoMethodError
,因為這樣預設的載入方法只能載入class,如果要載入module,必須跟class綁在一起,所以我們要載入有include該module的class(啥?你module只有單獨用嗎?那應該改成叫做class才對吧!)
假如我們有個controller使用該module例如:
class AppController < ApplicationController
include Greeter
end
那在spec檔案中就可以改寫如下:
require `rails_helper`
RSpec.describe AppController.new { include Greeter } do
it { expect(AppController.hello).to eq("hello world") }
end
這樣就可以囉!但需要注意兩個地方: 1. 要用AppController.new { include Greeter }
2. AppController.hello
代表需要用controller來啟動module中的method,而非使用module
說實在,這樣繞道有點遠,本人也還在想有什麼比較簡便的方法來載入module。大家有建議歡迎提供,謝謝。
2009年時就已經存在這個寫法:StackOverflow