C# - 如何使用 NSubstitute mock Ref out

最近在團隊中寫了不少的 unit test ,把一些 mock 的方式筆記下來~

這次筆記的是使用 NSubstitute mock ref out

這次使用的 mock library 是 NSubstitute.

MOCKS: What are they? When should you use them? – The Curious Programmer
MOCKS: What are they? When should you use them? – The Curious Programmer (jasonroell.com)

準備需要被 mock 的 interface

public interface ITestRefOut
{
  string RefOutFunction(string name, out string status);
}

Test Code

var testRefOut = Substitute.For<ITestRefOut>();

testRefOut.RefOutFunction(Arg.Any<string>(), out Arg.Any<string>())
          .Returns(x =>
           {
              x[1] = "mock status";
              return "something";
           });

Assert.AreEqual("something", testRefOut.RefOutFunction("mock Name", out var mockStatus ));
Assert.AreEqual("mock status", mockStatus);

利用 Substitute 建立 ITestRefOut 的 mock 實體
再 mock 這個 RefOutFunction 應該要回傳的值,這邊特別可以注意的是

x =>
{
  x[1] = "mock status";
  return "something"
}

x[1] 的 1 所代表的是這個 ref out 的位置,RefOutFunction 這個 function 中有兩個參數
第 [0] 個代表的是 name, 第 [1] 個代表的是 ref out 的 status
所以如果有這個 function 有更多的參數時,你需要注意 ref out 的位置是第幾個參數

碎念

其實我沒有很喜歡這種使用 ref out 的方式來做 function
因為使用了 ref out 的 function 除了他本身回傳的結果之外 他還「回傳」了 ref out 這個值
這讓我覺得它使得程式碼更加得複雜
如果在 C# 裡面需要回傳兩種值,我會比較偏好使用 C# 7.0 新增的 Tuple 語法的方式,或是回傳 type 的物件來做實作
紅底線的部分感謝 余小章 的補充~

參考資料:

nsubstitute 官方所提供的 mock ref out 文件
Setting out and ref args
https://nsubstitute.github.io/help/setting-out-and-ref-arguments/
特別去查了 ref out 的方法是否是一種程式碼的味道而找到了與自己想法相似的文章
Are out and ref modifiers in C# a code smell?
https://www.danylkoweb.com/Blog/are-out-and-ref-modifiers-in-c-a-code-smell-OC

以上是這次的筆記,不知道大家對於 C# 中的 ref out 的看法是如何呢~?

若有錯誤麻煩告知,感謝大家的收看!<(_ _)> 


在 FB 上有收到的回覆