2014-11-06

[讀書筆記] Interaction testing using mock objects

[讀書筆記] Interaction testing using mock objects

[前言]

在前一章Stubs 我們使用了Stub 來打破了Dependency
但是現實上 卻有很多的function是

沒有回傳值
沒有存狀態

針對這些Function該如何測試呢?

答案是 Mock Objects


1.1 Value-based vs. state-based vs. interaction testing



Value-based testing 
    Checks the value returned from a function.

State-based testing 
    Checks the noticeable behavior changes in the system under test, after changing its state.

Interaction testing
    Tests how an object sends input to or receives input from other objects—how that object interacts with other objects.

舉個例子:
假設有一個灌溉系統

Value-based testing 
    Check 水龍頭是否可以打開

State-based testing 
    Check 土壤濕度

Interaction testing
    在水龍頭端裝置一台監控設備 紀錄灌溉的起始結束時間以及水量 只需檢查監控設備的次數及水量是否正確

Sometimes state-based testing is the best way to go because interaction testing is too difficult to pull off.

State-based testing 有時是最好的測試方法 因為Interaction testing實在太難達到了

[Definition] 
Mock object
A mock object is a fake object in the system that decides whether the unit test has passed or failed. It does so by verifying whether the object under test interacted as expected with the fake object. There’s usually no more than one mock per test.


1.2 The difference between mocks and stubs


[Definition] 
Fake
A fake is a generic term that can be used to describe either a stub or a mock object, because they both look like the real object. Whether a fake is a stub or a mock depends on how it’s used in the current test. If it’s used to check an interaction (asserted against), it’s a mock object. Otherwise, it’s a stub.

Mocks 跟 Stubs最主要的區別如下圖:

Stub:
呼叫Assert的是 TestClass
code的例子:


Mock
用Mock Object來確認Test Pass or not


code的例子:


1.3: A simple handwritten mock example



假設新增一個需求:
當LogAnalyzer收到一個長度短於8的filename就呼叫外部WebService去記錄LogError

測試上 我們用MockWebService來替換掉外部WebService
此時我們要測的是 WebService是否確實有記錄到LogError


Why don't we write the tests directly inside the mock object code?
Reason:
1. We’d like to be able to reuse the mock object in other test cases, with other asserts on the message.
    要Reuse Mock Object

2. If the assert were put inside the mock object, whoever reads the test would have no idea what we’re asserting.
    寫在Mock裡 其他人會不知道在assert什麼


1.4 Using a mock and a stub together


假設再次新增一個需求:
如果WebService發生了Exception 系統要寄email給IT管理員

此時LogAnalyzer有兩個外部Dependence

如何測試當Exception發生時 有確實發送了Email?



Questions:

  • Why are we doing several asserts in a single test? How easy would it be to separate this test into three different tests with one assert each?Could the three asserts be combined into a single logical test?
  • It can be quite tedious to create manual mocks and stubs for each test or test class. How can we overcome that?
  • Couldn’t we have used the MockService from listing 4.1 as a stub?



1.5 One mock per test


Principle:

  • In a test where you test only one thing
  • Only one mock object in a test
  • Other fake objects are all stubs



1.6 Stub chains: stubs that produce mocks or other stubs


當一層接一層時 怎麼測試?
ex. 

你可能要寫 factory 跟 service兩個stubs
或者 Confuguration 跟 DBConfiguration兩個stubs

假如你想要替換掉 connstring
Solution:
1. 用Extract and Override    


2. 用Adapt Parameter Pattern


1.7 The problems with handwritten mocks and stubs


1. It takes time to write the mocks and stubs.

2. It’s difficult to write stubs and mocks for classes and interfaces that have many methods, properties, and events.

3. To save state for multiple calls of a mock method, you need to write a lot of boilerplate code to save the data.
<boilerplate : 照本宣科的規範;(新聞業)一成不變的陳腐文字>
為了在多次呼叫Mock Methods之後儲存狀態 需要寫很多code

4. If you want to verify all parameters on a method call, you need to write multiple asserts. If the first assert fails, the others will never run, because a failed assert throws an exception.
如果需要check 一個method的所有參數 需要多個 assert
但是只要一個assert Fail 就會中斷這次測試


5. It’s hard to reuse mock and stub code for other tests.


Related Posts:

  • [讀書筆記] Deploying and Releasing Applications Deploying and Releasing Applications 1.         Creating a Release Strategy           i.        … Read More
  • [心得文] 自動測試與TDD實務開發 Day2 Day2 的教學順序是先教我們怎麼使用Selenium做Web-Testing;中間則是介紹了FluentAutomation以及Page Objects;最後則是帶到了Refactoring。 而我的觀戰重點則是在於Refactoring。還記得以前我的Refactoring都是耗時費力,由上往下的設計模式。Refactor完也不敢保證有沒有side effect。Day2則是學到了如何有效攻克Refactoring。確實相當實用阿~ … Read More
  • 社群分享 在瀑布底下玩Scrum 今天很高興被AgileCommunity.tw邀請來跟各位分享一下我們Team的Practice 身在一個大型軟體公司稍微傳統的部門下也是能夠玩SCRUM的 這場sharing將會和大家分享我們在瀑布底下碰到問題之後 如何採用一些SCRUM的Practice以及Tool的協助來幫助我們解決問題 內容包括: Team Member的緊密配合 如何以JIRA視覺化我們的工作狀態 如何改善Standup Meeting的效率 如何在每次的Sp… Read More
  • [心得] Improvement Kata工作坊 - 讓員工自己變優秀的解藥(之一) 2015.05.21 Improvement Kata工作坊 - 讓員工自己變優秀的解藥(之一) 今晚參加Agile Meetup 2015 5月份聚會 今天的主題是講Improvement Kata 主要的重點在於 :  1. 了解現況 2. 確定目標 3. 持續改進 改進的重點在於套用kata的套路  持續練習固定的節奏與步驟來達成目標 … Read More
  • [心得文] 自動測試與TDD實務開發 Day1 [前情提要] [反省] 學習是要正面主動積極的 其實半年前我就想報名這堂課,不過可惜最後因為幾個負面思考而打消了念頭,當時在心中埋下了一顆悔恨的種子,告訴自己說,下次再有這個機會請不要錯過。 終於,今年盼到了第三梯的課程,雖然價格提高了4成 =.= ,不過還是自己能夠負擔的範圍啦,當然就報囉。 剛好今年也給了自己一些明確的目標: 1.     2015Q4 要在公司教授Unit Testing的… Read More

0 意見: