我注意到NSubstitute自动嘲笑以下类型:
虽然我知道这种情况发生了,但我无法找到原因来挑选这些类型。为什么不留下String
null?或者包含集合而不仅仅是Array
?
例如:
var crazyInterface = Substitute.For<ICrazyInterface>();
FileInfo[] folderContents = crazyInterface.FolderContents(@"C:\folder");
IObservable<FileInfo> fileObserver = crazyInterface.CreateNewFileObservable();
string fileHash = crazyInterface.FileHash(@"C:\folder\file.txt");
Task<byte[]> fileContents = crazyInterface.ReadFileContentsAsync(@"C:\folder\file.txt");
所有人都为他们实现了模拟,而List<T>
将为null(或任何其他引用类型)。
source code没有说明在AutoValues文件夹中实现自动模拟的原因。
答案 0 :(得分:2)
简短回答:特定的自动模拟类型刚刚添加,因为人们想要它们,我们觉得方便会超过因模拟或default(T)
可能预期返回真实值而造成的混乱。
如果有人对此感兴趣,我会回忆起这个功能的进化的更长,希望部分准确的故事。
NSubstitute开始为所有事情返回default(T)
。对于我们有调用链的情况,这会很痛苦,所以我们为接口类型添加了自动模拟。这是一个相当安全的操作 - 与类不同,实际代码没有可能从构造函数调用或无意中调用非虚方法运行。例如,mySub.SomeAutoSub().DoStuff()
可以根据SomeAutoSub()
的返回类型运行实际代码。
下一个安全级别是包含所有虚拟成员和默认构造函数的类。文档将论文称为pure virtual classes。拥有虚拟成员意味着如果我们深入了解自动子窗口实例,我们就不会意外地调用实际代码。现在这仍将通过构造函数运行实际代码,但它不会采用参数,因此我们可以假设(读取:交叉指和希望)默认行为将做一些合理的事情,而不是做任何可怕的事情。
最后,您指出的例外案例有Array
和Task
。当我们觉得方便性超过任何混乱时,这些都是基于反馈完全临时添加的。我们想要避免的主要问题是在预期模拟时返回实际值。如果你不小心打电话给.Returns
一些不是模拟的东西,NSubstitute也不会很好。
Strings
,Arrays
和Tasks
符合此标准。你不能模拟这些类型,因此在测试中有一个合理的默认值似乎是合理的。我发现由于null默认值,我经常遇到爆炸的字符串操作,所以为了方便,我添加了一个。其他人希望默认Task
能够合理地工作,因此增加了。我不记得没有自动提交集合背后的原因(可能是因为有些人使用IList<T>
的模拟版本,其中提供像List<T>
这样的特定实现更容易明确存根?)。
我认为我们可以在这里避免一些不一致,因为我们处于测试环境中 - 如果我们需要特定的值或行为,我们将明确地将其删除。否则,我们会得到一个默认值,希望不会阻碍。
如果您想要自动附加内容,请点击discussion group。现在更难做出这样的潜在破坏性改变,但如果特定类型有令人信服的案例,我们可以考虑将其添加进去。