シングル責任原則はここにあなたの親友です。
まず、AllFromCache()をリポジトリクラスに移動し、GetAll()を呼び出します。キャッシュから取得することは、リポジトリの実装の詳細であり、呼び出し元のコードで認識されるべきではありません。
これにより、フィルタリングクラスを簡単にテストできます。取得元を気にしなくなりました。
次に、データベース(またはどこからでも)からデータを取得するクラスをキャッシングラッパーでラップします。
AOPはこれに適した手法です。それは非常に得意な数少ないものの一つです。
PostSharpなどのツールを使用して、選択した属性でマークされたメソッドがキャッシュされるように設定できます。ただし、これがキャッシュしている唯一のものである場合、AOPフレームワークを使用する必要はありません。同じインターフェイスを使用し、それを呼び出し元のクラスに挿入するリポジトリとキャッシングラッパーを用意するだけです。
例えば。
public class ProductManager
{
private IProductRepository ProductRepository { get; set; }
public ProductManager
{
ProductRepository = productRepository;
}
Product FetchById(guid id) { ... }
IList<Product> FilterByPropertry(int property) { ... }
}
public interface IProductRepository
{
IList<Product> GetAll();
}
public class SqlProductRepository : IProductRepository
{
public IList<Product> GetAll()
{
// DB Connection, fetch
}
}
public class CachedProductRepository : IProductRepository
{
private IProductRepository ProductRepository { get; set; }
public CachedProductRepository (IProductRepository productRepository)
{
ProductRepository = productRepository;
}
public IList<Product> GetAll()
{
// Check cache, if exists then return,
// if not then call GetAll() on inner repository
}
}
ProductManagerからリポジトリ実装の知識をどのように削除したかをご覧ください。また、データ抽出を処理するクラス、データ取得を処理するクラス、およびキャッシュを処理するクラスを持つことにより、単一責任原則をどのように遵守しているかを参照してください。
これで、これらのリポジトリのいずれかでProductManagerをインスタンス化して、キャッシュを取得するかどうかを決定できます。これは、キャッシュの結果であると思われる紛らわしいバグを取得したときに非常に便利です。
productManager = new ProductManager(
new SqlProductRepository()
);
productManager = new ProductManager(
new CachedProductRepository(new SqlProductRepository())
);
(IOCコンテナを使用している場合は、さらに優れています。適応方法は明らかです。)
そして、ProductManagerテストで
IProductRepository repo = MockRepository.GenerateStrictMock<IProductRepository>();
キャッシュをテストする必要はまったくありません。
質問は次のようになります:CachedProductRepositoryをテストする必要がありますか?しないことをお勧めします。キャッシュはかなり不確定です。フレームワークは、あなたが制御できないものをそれで処理します。たとえば、いっぱいになったときに、そこから何かを削除するだけです。あなたはブルームーンで一度失敗するテストになってしまいます、そしてあなたは本当にその理由を理解することは決してないでしょう。
そして、私が上で提案した変更を行った後、そこにテストするロジックはそれほど多くありません。本当に重要なテストであるフィルタリングメソッドがそこにあり、GetAll()の詳細から完全に抽象化されます。GetAll()だけ...すべてを取得します。どこかから。