這必須是微不足道的,但對TDD來說是相當新的,我找不到正確的方法來做到這一點。如何正確地模擬.NET 3.5
比方說,我們有一個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 <模塊>隱式轉換爲System.Collections.Generic.IEnumerable <的IModule >
哪個與this相同。
現在,一定有一些微不足道的東西可以逃脫我。據我所知,使LoadModules()
返回IEnumerable<IModule>
合格作爲一件好事™。將返回類型更改爲IEnumerable<Module>
當然會使代碼編譯,但它只會將問題轉移到單元測試。
我有點困惑,也許我做的都是錯的(我很抱歉,如果是這樣的話)。
那麼,你會怎麼做呢?我如何使Module
可嘲弄?
更換
new Module(dll)
所以......就是這樣,是吧?簡單的演員。我真的需要一個假期。謝謝你,@DevinB。爲什麼我必須將一個實現了某個接口的類的實例投射到同一個接口上的確切原因仍然不太清楚,我想我必須真正閱讀Eric Lippert關於差異的文章。順便說一下,替換'var'並不是真的需要,如果真的需要,我會非常驚訝。再次感謝。 – 2012-04-27 19:27:55我知道替換var並不是真的需要,但最好清楚一點,特別是在像這樣的情況下,整個問題是LINQ查詢返回一個意外的類型。在這種情況下,清晰度是發現和消除漏洞的最重要因素。 – DevinB 2012-04-27 19:34:34
公平點,DevinB。非常感謝你。現在我可以嘲笑:) – 2012-04-27 19:41:57