Supponiamo che abbia un'interfaccia che dichiara la seguente firma del metodo:
SearchResults SearchProducts(string type, string filter, string anotherFilter);
All'interno di una concreta implementazione di questo, istanzio una classe helper (chiamiamola QueryBuilder
), costruita per facilitare la costruzione di query di ricerca strongmente tipizzate per la specifica libreria di ricerca che sto usando . Voglio test unitario SearchProducts
(idealmente prendendo in giro il generatore di query), il che significa che ho bisogno di disaccoppiare il metodo da QueryBuilder
.
Come faccio a farlo in modo appropriato quando le due cose sono accoppiate logicamente ? Vale a dire:
- Non è appropriato passare un
IQueryBuilder
nel metodo poiché l'implementazione diIQueryBuilder
è strettamente accoppiata all'implementatore diISearchProducts
, cioè i tipi dei valori di ritorno dei metodi diQueryBuilder
sono specifici per la libreria utilizzata nel concretoSearchService
. - Non è appropriato passare un'istanza di
IQueryBuilder
nel costruttoreSearchService
(tramite DI o direttamente) poiché l'ambito logico dell'istanza del generatore di query è locale al metodoSearchProducts
call - viene istanziato nel metodo, il suo stato viene manipolato aggiungendo subquery e una "query" completa viene estratta per questa chiamataSearchProducts
).
Quindi, visto quanto sopra, qual è il modo appropriato di gestirlo? Sembra un caso per una fabbrica; tuttavia l'implementazione di questa fabbrica sarebbe banale e sembra un po 'forzato definire un'interfaccia factory e aggiungere un parametro costruttore solo per motivi di testabilità.
Questo è un indizio di un difetto fondamentale nella progettazione della mia interfaccia di ricerca? Come faccio a disaccoppiare queste cose in modo tale da poter testare sia il servizio di ricerca che le implementazioni del generatore di query in isolamento?