測試中的 Mock 跟 Stub 代表什麼
Mock 跟 Stub 這兩個名詞,在我試圖寫有關第三方 API 的相關測試時,一直困擾著我,到底我現在用的是 mock 還是 stub??
我並不能百分之百確定我講的是對的,但我希望能用比較有公信力的方法,用我自己能懂的語言理出一番頭緒 XD
首先我先參考 Everyday Rails Spec 這本書的內容,畢竟能出書的應該也能稱得上是位大大吧!?這本書的 155 頁提到以下內容
A mock is some object that represents a real object for testing purposes.These are also known as test doubles. The mock stands in for an object we may previously have used a factory or PORO to create. However, a mock doesn’t touch the database–and thus takes less time to set up in a test.
A stub overrides a method call on a given object and returns a predetermined value for it. In other words, a stub is a fake method which, when called upon, will return a real result for use in our tests. You’ll commonly use this to override the default functionality for a method, particularly in database or network- intensive activity.
這裏提到 mock 在測試裡代表著一個真實物件,它的特性是不會去接觸到資料庫,因此在測試上可以花較少時間,OK,這樣的定義範圍超廣,很安全 XD
Stub 則代表著一個虛擬的方法,在這個測試中這個方法一但被呼叫,就是用 stub 的回傳值代替原本的方法.對我來說有點像遊戲裡面的 NPC,你問他指定問題的話他會跟你說答案,問他預期以外的問題就會不回答或者壞掉.
讓我們來看看另一篇文章
A Test Stub is a fake object that’s used in place of a real object for the purpose of getting the program to behave the way we need it to in order to test it. A big part of a Test Stub’s job is to return pre-specified hard-coded values in response to method calls.
A Mock Object is a fake object that’s used in place of a real object for the purpose of listening to the methods called on the mock object. The main job of a Mock Object is to ensure that the right methods get called on it.
在這篇文章中,對於 stub 的解釋跟上面講到的差不多.差別在於 mock 的部分這一篇想要講的更具體:他認為 mock 是一個假的物件,專門做來接收方法,也就是說 mock 主要是用來操作跟 “行為” 相關的命令,這篇的概念跟另一個網站上講得差不多
結論
我認為 stub 的定義爭議不算太大,如果要解釋它的話:
Stub: 一個 NPC ,接受特定訊息之後會回傳我們指定的內容
主要的爭議在於 mock ,我比較傾向給他一個廣泛的解釋,像是一開始那本書定義的那樣,但有兩件事情不能變:
1.Mock 代表一個真實物件 2.Mock 不會碰到資料庫
畢竟 mock 的英文翻譯就是: 假的,這麼廣義的字其實非常容易被大家濫用,沒辦法說誰的說法對錯,不過在測試這領域提到 mock 的話,我認為還是要保有上面的兩個原則
另外,在 stackoverflow 或者其他文章,其實有著許多互相衝突的解釋版本,比方說有人會說 stub 根本不會回傳值,或者 mock 才不會回傳值等等… 我認為其實可能在不同語言裡面,他們的小圈子分別對於 mock / stub 有不同的釋義,又或者某些語言裡面已經規定了 mock 跟 stub 這兩種物件的用法,所以我覺得這是沒有戰完的一天的 XD
參考資料:
RSpec mocks and stubs in plain English