Mocking di oggetti non copiabili

1

Mi trovo spesso nella situazione in cui voglio prendere in giro un oggetto non copiabile, ad esempio un handle DbHandle .
Stavo andando avanti e indietro guardando diverse scelte di design, e ho optato per il seguente disegno:

Nel mio codice di produzione, non è necessario che un client di Repository conosca l'oggetto DbHandle , ma per i test di unità, questo oggetto DbHandle è esattamente quello che voglio prendere in giro.
Ho optato per unique_ptr perché chiariscono che Respository possiede DbHandle , anche se è stato creato all'esterno.

#include <memory>

class Repository {
public:
    Repository() : d_dbHandel(std::unique_ptr<DbHandel>(new DbHandle("default"))) {
        d_dbHandel->open("myDB");
    }

    Repository(std::unique_ptr<DbHandle> DbHandle) :
        d_dbHandel(std::move(DbHandle) {
    }

    inline DbHandle& getDbHandel() {
        return *d_dbHandel;
    }

private:
    std::unique_ptr<DbHandel> d_dbHandel;
};

Quali sono alcuni dei difetti di questo approccio?

    
posta user695652 29.07.2016 - 00:39
fonte

1 risposta

1

Ciò che fai è per lo più corretto.

Puoi chiederti se non stai esponendo il tuo codice semplicemente a causa dei test. Questa è davvero una mancanza. Il client non ha bisogno di conoscere il DbHandle , ma Repository non lo è neanche! A rigor di termini, come puoi testare unitamente il repository se dipende da (sa) un'implementazione concreta DbHandle ?

Quindi la soluzione è sempre iniettare DbHandle , dal test unitario o da una classe wrapper o dalla funzione factory e usare una classe astratta DbHandle . Crea una classe concreta derivata DbDefault che viene normalmente utilizzata.

Inoltre, sconsiglio di esporre i membri tramite Getter come nella funzione getDbHandel ().

Questo potrebbe essere un design migliorato:

#include <memory>

std::unique_ptr<Repository> createRepository()
{
    return std::make_unique<Repository>( std::make_unique<DbDefault>() );
} 

class Repository {
public:
    explicit Repository(std::unique_ptr<DbHandle> dbHandle) :
        d_dbHandel(std::move(dbHandle) {
}

void storeValue(double x) {
    d_dbHandel->storeValue(x);
}

private:
    std::unique_ptr<DbHandel> d_dbHandel;
};
    
risposta data 15.08.2016 - 13:39
fonte

Leggi altre domande sui tag