Il principio di responsabilità singola è il tuo migliore amico qui.
Prima di tutto sposta AllFromCache () in una classe repository e chiamala GetAll (). Che recuperi dalla cache è un dettaglio di implementazione del repository e non dovrebbe essere conosciuto dal codice chiamante.
Questo rende la verifica della classe di filtro semplice e facile. Non ti interessa più da dove lo stai ricevendo.
In secondo luogo, avvolgere la classe che ottiene i dati dal database (o da qualsiasi luogo) in un wrapper di memorizzazione nella cache.
AOP è una buona tecnica per questo. È una delle poche cose a cui è molto bravo.
Utilizzando strumenti come PostSharp , puoi configurarlo in modo che qualsiasi metodo contrassegnato da l'attributo scelto verrà memorizzato nella cache. Tuttavia, se questa è l'unica cosa che si sta memorizzando nella cache, non è necessario arrivare ad avere un framework AOP. Basta avere un repository e un Caching Wrapper che utilizzino la stessa interfaccia e inseriscili nella classe chiamante.
ad es.
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
}
}
Scopri come hai rimosso le conoscenze sull'implementazione del repository da ProductManager? Guarda anche come hai aderito al Principio di Responsabilità Unica avendo una classe che gestisce l'estrazione dei dati, una classe che gestisce il recupero dei dati e una classe che gestisce la cache?
Ora è possibile creare un'istanza di ProductManager con uno di questi repository e ottenere il caching ... o meno. Questo è incredibilmente utile in seguito quando si ottiene un bug confuso che si sospetta sia un risultato della cache.
productManager = new ProductManager(
new SqlProductRepository()
);
productManager = new ProductManager(
new CachedProductRepository(new SqlProductRepository())
);
(Se stai usando un contenitore IOC, ancora meglio. Dovrebbe essere ovvio come adattarsi.)
E, nei tuoi test ProductManager
IProductRepository repo = MockRepository.GenerateStrictMock<IProductRepository>();
Non è necessario testare la cache.
Ora la domanda diventa: dovrei provare quel CachedProductRepository? Suggerisco di no Il cache è abbastanza indeterminato. Il framework fa cose che sono fuori dal tuo controllo. Ad esempio, rimuovendo qualcosa da esso quando diventa troppo pieno, per esempio. Finirai con test che falliscono una volta in una luna blu e non capirai mai veramente perché.
E, avendo apportato le modifiche sopra suggerite, non c'è davvero molta logica da testare lì. Il test davvero importante, il metodo di filtraggio, sarà presente e completamente estratto dal dettaglio di GetAll (). GetAll () solo ... ottiene tutto. Da qualche parte.