这必须是微不足道的,但是对于 TDD 来说还是很新的,我想不出正确的方法来做到这一点。
假设我们有一个 WinForms 应用程序,作为其启动过程的一部分,它在给定文件夹中查找 DLL 以动态填充其主菜单栏。
这些 DLL 只是插件:它们都实现了一个接口,并且它们都将显示为菜单项。真的就这么简单。
我们将每个 DLL 称为Module
.
现在,我想“嘿,史蒂夫,你将不得不模拟这些Module
对象。让我们定义一个名为 的接口IModule
,并让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()
不会编译,因为——据我所知——差异问题。
错误信息如下:
无法将类型 System.Collections.Generic.IEnumerable<Module> 隐式转换为 System.Collections.Generic.IEnumerable<IModule>
这与这个问题相同。
现在,一定有一些琐碎的事情让我无法理解。据我所知,LoadModules()
退货IEnumerable<IModule>
是一件好事™。将返回类型更改IEnumerable<Module>
为当然会使代码编译,但它只会将问题转移到单元测试。
我有点困惑,也许我做错了(如果是这种情况,我很抱歉)。
那么,你会怎么做呢?我如何制作可Module
模拟的?