2015年9月1日 星期二

NSubstitute 練習題 - void 不回傳值方法但有使用到 out 參數

嗯…… 好久沒有寫文章,再次寫文章的題目卻讓人搞不太清楚,簡單來說就是看下面圖會比較清楚,

image

不要問為何會有這樣的程式,又為何要這麼樣設計與使用,那個不是重點,重點在於怎麼去對這一段程式去做測試。

 


計算兩點座標距離的程式在 GeographyService 的 ValidateDistance 方法裡,

介面:IGeographyService

image

實作:GeographyService

image

如果兩點座標距離超過 20000 公尺,就會拋出 InvalidOperationException 例外,不超過的話則是把計算後的距離放到 out distance 參數當中。

這裡的計算兩個座標點的距離會使用到 System.Device 參考,然後 GeoCoordinate 類別的擴充方法 GetDistanceTo() 的命名空間則是在 System.Device.Location,

SNAGHTML8d612d

MSDN - System.Device.Location 命名空間 ()

MSDN - GeoCoordinate.GetDistanceTo 方法 (System.Device.Location)

 

而 SampleContext 類別的 FooMethod 方法會使用 GeographyService 的 ValidateDistance() 方法,

image

主要是測試 SampleContext.FooMethod 對於兩個座標點計算距離之後的處理,對於原本 GeographyService.ValidateDistance() 方法的實作內容並不是目前要測試的主要目標,所以這邊就會使用 NSubstitute 來建立 IGeoprahpyService 的 Stub 物件。

下面的寫法看起來沒有什麼問題,

image

而且測試也會過

image

但是實際上因為沒有真正的執行到 GeographyService.ValidateDistance() 實作裡,所以不會真的去計算兩個座標點的距離,所以上面的測試所使用到的 distance 都一直是零(int 的初始值)。

 

怎麼測?

問題來了,一個 void 修飾方法是不會有回傳值,而且把值給傳遞到使用端的是透過 out 參數,這樣的情況要怎麼在單元測試方法裡用 NSubstitute 去完成測試呢?

 

直接看 NSubstitute 的文件,會用到以下的兩篇文件裡的方式,

NSubstitute: Callbacks, void calls and When..Do

NSubstitute: Setting out and ref args

將原本的方法依據上面兩篇文件說明的方式做了修改。因為是修飾詞為 void 的不回傳值的方法,所以也無法使用 Returns(),但是有個 out 參數要把計算後的距離給傳遞出來,所以就使用了 When … Do… 方法,然後在 Do… 這裡 out 參數要傳遞出來的值。

image

大家對於上面 Do…  裡面的 x[4] 會有點質疑,為什麼是用「4」呢?
其實那個「4」所指的是方法簽章裡的參數索引數,由零開始算,而 ValidateDistance() 方法簽章的索引位置為四的就是 out int distance 這個參數。

如果方法簽章裡有多個 out 或是 ref 參數也是使用相同的做法,可以指定多個參數,不過要指定好參數的索引位置。

以偵錯模式進入單元測試裡,實際去看看測試執行的時候是不是就是真如我們所指定的,out int distance 是傳遞指定的「500」?

進入偵錯模式之後可以觀察到 out distance 參數的確是使用我們再單ˋ原測試裡所指定的 500.

image

其他針對不同 distance 決定不同的 message 情境也使用相同的情境一併完成單元測試,

image

image

image

 

看起來這邊好像都已經把這邊的使用情境都測試到了,不過還是有一個部分忘記測了,那就是兩個座標點位置的距離如果超過 20000m 的時候就會拋出例外,這個部分還是需要被測試到,至於怎麼測這個例外呢?

其實做法跟這一篇所講的是差不多,只是有一點點不同,不過這個部分就下一篇再來說吧。

 

參考連結

MSDN - System.Device.Location 命名空間 ()

MSDN - GeoCoordinate.GetDistanceTo 方法 (System.Device.Location)

NSubstitute: Callbacks, void calls and When..Do

NSubstitute: Setting out and ref args

NSubstitute完全手册索引 - Dennis Gao - 博客园

[C#.NET] 單元測試 Mock Framework - NSubstitute - 余小章 @ 大內殿堂- 點部落

 

想要更加瞭解測試與敏捷開發,就一定要關注 91 哥的「91 敏捷開發之路」Facebook 粉絲專頁
https://www.facebook.com/91agile

 

以上

1 則留言:

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。