这一定是微不足道的,但作为 TDD 的新手,我无法找出正确的方法来做到这一点。
假设我们有一个 WinForms 应用程序,作为其启动过程的一部分,它会在给定文件夹中查找 DLL 以动态填充其主菜单栏。
那些 DLL 只是插件:它们都实现了一个接口(interface),并且它们都将显示为菜单项。就这么简单。
让我们将每个 DLL 称为 Module
.
现在,我想“嘿,史蒂夫,你必须模拟这个 Module
对象。让我们定义一个名为 IModule
的接口(interface),并让 Module
类实现它。这样你就可以模拟它们如你所愿”。
所以,让我写几行代码,具体来说 IModule
和Module
(我是在没有编译器支持的情况下直接写的,所以它可能无法编译):
<!-- language: c# -->
public interface IModule {
string Id { get; }
string DisplayName { get; }
}
public class Module : IModule {
public string Id { get; }
public string DisplayName { get; }
public string Path { get; private set; }
public Module(FileInfo path) {
Path = path.FullName;
}
}
并且,当我们这样做时,让我们实现将执行实际加载的类:
public class ModuleLoader {
IEnumerable<DirectoryInfo> SearchPaths;
public ModuleLoader(IEnumerable<DirectoryInfo> searchPaths) {
SearchPaths = searchPaths;
}
public IEnumerable<IModule> LoadModules() {
var modules = SearchPaths
.Where(dir => dir.Exists)
.SelectMany(dir => dir.GetFiles("*.dll").Select(dll => new Module(dll)));
return modules;
}
}
问题来了:LoadModules()
不会编译,因为——据我所知——方差问题。
错误信息如下:
Cannot implicitly convert type System.Collections.Generic.IEnumerable<Module> to System.Collections.Generic.IEnumerable<IModule>
与 this 相同问题。
现在,一定有什么琐事让我忽略了。据我所知,使LoadModules()
返回IEnumerable<IModule>
有资格成为一件好事™。将返回类型更改为 IEnumerable<Module>
当然可以使代码编译,但它只是将问题转移到单元测试。
我有点困惑,也许我做错了(如果是这样的话,我很抱歉)。
那么,你会怎么做呢?我该如何制作Module
可 mock 吗?
最佳答案
您应该替换var
与 IEnumerable<IModule>
并替换new Module(dll)
与 (IModule) (new Module(dll))
关于c# - 如何在 .NET 3.5 中正确模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10356377/