È buona prassi registrare le creazioni di sviluppo utilizzando la compilazione condizionale?

7

Sto sviluppando un'applicazione che si collega a un database e sto utilizzando DI / IOC. Quando si esegue l'intera applicazione durante lo sviluppo, voglio naturalmente evitare di colpire il DB. Attualmente, ho qualcosa di simile nella mia composizione root (usando SimpleInjector):

#if DEBUG
    container.Register<IDbActions, MockDbActions>();
#else
    container.Register<IDbActions>(() => new RealDbActions(someParameter));
#endif

Questa è una buona pratica o esiste un modo migliore per registrare i mock utilizzati per l'esecuzione dell'intera applicazione durante lo sviluppo?

Modifica: non si tratta di test unitari. Tutte le classi possono essere testate unitamente a prescindere da ciò che si trova nella radice della composizione, perché il contenitore IOC è (naturalmente) mai usato durante il test dell'unità.

    
posta cmeeren 20.02.2017 - 19:10
fonte

3 risposte

7

Non sono d'accordo con questa pratica.

  1. Se un tester di unità sta scrivendo un test e vuole prendere in giro il database in un certo modo, il tuo codice potrebbe interferire con tale sforzo. Avrebbe dovuto prendere in giro la tua finta.

  2. In che modo testare il codice dell'unità non compilato in modalità di debug (l'istanziazione di RealDbActions )? Nel tuo esempio, la costruzione è banale, ma in alcuni casi potrebbe non esserlo.

  3. Non sarà possibile eseguire test di integrazione automatici se il progetto è compilato in modalità di debug (l'integrazione viene messa in ridicolo). Se si compila in modalità di rilascio, potrebbe essere molto più difficile analizzare i risultati.

  4. Il tuo codice base sarà inquinato con tutti i tuoi tipi di simulazione. Anche se li escludete dalla compilazione, si trovano nell'albero dei sorgenti e potrebbero influire su diff, unioni e altre attività comuni ogni volta che vengono modificati.

  5. Mentre una classe MockDbActions sottile potrebbe non essere così male, cosa succede se ha delle dipendenze (ad esempio una libreria di derisione)? Hai intenzione di includere riferimenti a quelli del tuo progetto principale? Verrà distribuito nel tuo data center di produzione? (Per quanto ne so, Visual Studio non supporta direttive di compilazione condizionale per riferimenti).

risposta data 21.02.2017 - 04:06
fonte
2

Non sono in disaccordo con questa pratica in generale, ma la userei come ultima risorsa. Aneddoticamente, l'ho usato durante la scrittura di applicazioni che collegano e leggono l'hardware del sensore, ma non disponevano di hardware fisico disponibile, quindi senza l'eliminazione delle comunicazioni hardware l'applicazione non sarebbe stata in grado di funzionare nel suo complesso.

Quindi, se non hai un database per funzionare contro qualsiasi cosa, puoi usare questo in un pizzico per essere in grado di eseguire la tua app, ma preferibilmente colpire un database di test, e mantenere gli script per ripristinare i dati di test in uno stato noto , se applicabile.

    
risposta data 21.02.2017 - 12:54
fonte
0

Come ha detto @John Wu, la soluzione ha il rovescio della medaglia, che mescola codice produttivo e di derisione.

Un'opzione per evitare che potrebbe essere quella di spostare "DEV < > PROD switch" nella configurazione. Per esempio. per il framework di entità (prima il codice), è facilmente possibile utilizzare un database leggero in memoria invece di un dbms pesante. Il file di configurazione può essere configurato in base alla configurazione di build (DEBUG / RELEASE).

Se ciò non è possibile e hai una logica di derisione (più di una classe vuota), proverei a spostare la logica di simulazione nella propria assemblea per avere un confine chiaro.

Tuttavia, nel tuo caso (con una classe vuota), vorrei semplicemente aggiungere un commento in cima al file e lasciarlo nello stesso progetto ...;)

    
risposta data 21.02.2017 - 11:53
fonte