題目有點難定,這麼做個簡單的說明,在一個使用情境裡會使用到同個類別的同個方法多次,然後第一次執行的結果與後續幾次的執行結果會有所不同。例如在一個使用情境裡,方法裡會使用到一個物件 collection,然後會去使用另一個類別的方法做多次處理(比方說,刪除),執行第一次與後續幾次的執行就會有不同的回傳結果。
如果要對這個使用情境去做單元測試時,以上的那個執行多次的類別方法是需要被隔離,使用 NSubstitute 建立 stub 與預期回傳值,那麼應該怎麼處理呢?
這是上週同事向我詢問的一個問題,在印象中好像我並沒有實作過類似的操作情境,所以也對於怎麼在單元測試裡去處理這樣的狀況是有點陌生,所以找了一下相關的實作方式,最後還是在 NSubstitute 官網的說明文件裡找到方式,以下就來做說明。
下面的 FooContext 類別的 JustDemoProcess 方法就是我們要測試的目標,會用到有實作ICustomerService 介面的類別裡面的 SomeProcess 方法,而且會使用到兩次,兩次的回傳結果會不同,
以下是 FooContext 類別的 JustDemoProcess 方法裡會使用到的另一個介面定義,JsutDemoProcess 方法會去使用 SomeProcess 方法,裡面怎麼實作就不去管他
這要怎麼測試呢?
如果是很直覺的直接使用 NSubstitute 去建立 stub 的話,就應該會是下面的做法,以下的單元測試方法裡有使用的「AutoFixture」這個套件建立測試資料。
以下的單元測試 Arrange 內容看起來是蠻正常的,似乎都有依據實際的使用情境去做設定以及給予預期執行 ICustomerService.SomeProcess 方法的回傳結果,而且依照這個單元測試去實際執行也會得到綠燈,但是… 確有很大的問題,
進入偵錯模式看看 FooContext 的 JustDemoProcess 方法的執行時的內容,
原本預期第一次執行 ICustomerService.SomeProcess() 方法的回傳值 Customers 數量會有兩個,但是觀察偵錯模式的執行卻是看到兩次的執行回傳 Customers 數量都是一個,也就是說用 NSubstitute 所建立的兩個 stub,最後是只用到了最後所設定的。
應該怎麼做呢?
前面有說到,其實在 NSubstitute 官網的說明文件裡就有說明應該要怎麼處理,
NSubstitute: Multiple return values
簡體中文的說明翻翻譯:
NSubstitute完全手册(七)设置多个返回值 - 匠心十年 - 博客园
於是單元測試的程式內容要改成以下的方式,
進入偵錯模式觀察執行的內容
從上面的執行內容就可以看到第一次執行 ICustomerService.SomeProcess() 與第二次執行的回傳值就會不同了,而且是依據我們所指定的預期內容來回傳。
使用並且比較過多種 Mock 工具的使用,會發現到 NSubstitute 的確是比其他一些 Mock 工具還要來得方便與簡易。
參考連結
NSubstitute: Multiple return values
NSubstitute完全手册(七)设置多个返回值 - 匠心十年 - 博客园
相關連結
Github - AutoFixture/AutoFixture
延伸閱讀
Mocking: why we picked NSubstitute - Adaptive
以上
沒有留言:
張貼留言