これは些細なことですが、TDDにとって非常に新しくなっているため、適切な方法を見つけることができません。.NET 3.5を正しく模擬する方法
スタートアッププロセスの一環として、特定のフォルダ内のDLLを探してメインメニューバーを動的に読み込むWinFormsアプリケーションがあるとします。
これらの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 <はIModule >
にタイプSystem.Collections.Generic.IEnumerable <モジュール>を変換できません。 thisと同じです。
今、私を逃れるような些細なことがあるはずです。私の知る限りでは、LoadModules()
の返品IEnumerable<IModule>
はGood Thing™となります。戻り値の型をIEnumerable<Module>
に変更すると、コードはコンパイルされますが、問題は単体テストに移動するだけです。
私はちょっと混乱しています。多分私はそれをすべて間違ってやっています(私はそれが事実なら謝ります)。
これはどうでしょうか? Module
をどうやって見事にするには?
で
new Module(dll)
を置き換えるので...それはね、それだでしょうか?シンプルなキャスト。私は本当に休暇が必要です。ありがとう、@DevinB。なぜ私は同じインターフェイスに特定のインターフェイスを実装するクラスのインスタンスをキャストしなければならない正確な理由は、私にはまだ多少不明です、私は本当に分散についてのEric Lippertの投稿を読む必要がありますね。ところで、 'var'を置き換えることは本当に必要なことではありません。本当に驚いています。再度、感謝します。 –私はvarの交換は本当に必要ではないことを知っていますが、特にこのようなケースでは、LINQクエリが予期しないタイプを返す問題があることが明確です。このような場合、明確さは、バグを見つけて除去する上で最も重要な要素です。 – DevinB
Fair point、DevinB。どうもありがとうございました。今私は離れて嘲笑することができます:) –