2011-09-30 11 views
37

Ho una fabbrica che restituisce un puntatore intelligente. Indipendentemente da quale puntatore intelligente utilizzo, non riesco a convincere Google Mock a prendere in giro il metodo factory.Google può simulare un metodo con un tipo di ritorno puntatore intelligente?

L'oggetto fittizio è l'implementazione di un'interfaccia astratta pura in cui tutti i metodi sono virtuali. Ho un prototipo:

MOCK_METHOD0(Create, std::unique_ptr<IMyObjectThing>()); 

E ottengo:

"...gmock/gmock-spec-builders.h(1314): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'" 

Il tipo indicò nel puntatore intelligente è definito.

E ho capito che sta provando ad accedere a uno dei costruttori dichiarato privato, ma non capisco perché. Quando questo era uno std :: auto_ptr, l'errore diceva che non esisteva un costruttore di copia, il che mi confonde.

In ogni caso, esiste un modo per simulare un metodo che restituisce un puntatore intelligente? O c'è un modo migliore per costruire una fabbrica? La mia unica decisione è di restituire un puntatore raw (blech ...)?

Il mio ambiente è Visual Studio 2010 Ultimate e Windows 7. Non utilizzo la CLI.

risposta

-1

Google Mock richiede, nella maggior parte dei casi, parametri e valori restituiti dai metodi di simulazione. Per boost's documentation, unique_ptr non è copiabile. Hai la possibilità di restituire una delle classi di puntatori intelligenti che utilizzano la proprietà condivisa (shared_ptr, link_ptr, ecc.) E sono quindi copiabili. O puoi usare un puntatore raw. Poiché il metodo in questione è apparentemente il metodo che costruisce un oggetto, non vedo alcun problema inerente con la restituzione di un puntatore raw. Finché si assegna il risultato a qualche puntatore condiviso in ogni sito di chiamata, starai bene.

+31

Non dovresti aver bisogno di fare cambiamenti nelle interfacce delle tue classi solo per farle lavorare con il tuo framwork beffardo.Spesso questo non è affatto possibile. Questa non è una soluzione accettabile per me! –

+12

Non mi sembra accettabile che una classe factory restituisca un puntatore non elaborato. In questo caso, unique_ptr ha più senso. È stato progettato in parte per risolvere il problema di "assegnare il risultato a un puntatore condiviso su * ogni * sito di chiamate". –

+3

Non penso che questa sia la risposta corretta, cambiando tutto in proprietà raw o condivisa non è una soluzione solo per mettere alla prova le cose! – paulm

78

Una possibile soluzione alternativa per i problemi di google mock framework con argomenti di funzione non copiabili (const) e valori di retun consiste nell'utilizzare metodi di proxy proxy.

Supponiamo di avere la seguente definizione di interfaccia (se è buono stile da utilizzare std::unique_ptr in questo modo sembra essere più o meno una questione filosofica, io personalmente piace far rispettare trasferimento della proprietà):

class IFooInterface { 
public: 
    virtual void nonCopyableParam(std::unique_ptr<IMyObjectThing> uPtr) = 0; 
    virtual std::unique_ptr<IMyObjectThing> nonCopyableReturn() = 0; 
    virtual ~IFooInterface() {} 
}; 

la classe finta appropriata potrebbe essere definita in questo modo:

class FooInterfaceMock 
: public IFooInterface { 
public: 
    FooInterfaceMock() {} 
    virtual ~FooInterfaceMock() {} 

    virtual void nonCopyableParam(std::unique_ptr<IMyObjectThing> uPtr) { 
     nonCopyableParamProxy(uPtr.get()); 
    } 
    virtual std::unique_ptr<IMyObjectThing> nonCopyableReturn() { 
     return std::unique_ptr<IMyObjectThing>(nonCopyableReturnProxy()); 
    } 


    MOCK_METHOD1(nonCopyableParamProxy,void (IMyObjectThing*)); 
    MOCK_METHOD0(nonCopyableReturnProxy,IMyObjectThing*()); 
}; 

Hai solo bisogno di prendersi cura, che le configurazioni (le azioni intraprese) per la nonCopyableReturnProxy() metodo di ritorno sia NULL o un Instan e allocati dinamicamente nell'heap.


C'è una google-mock user forum thread discutere di questo argomento in cui uno dei manutentori afferma che il quadro google-finta non verrà modificato per sostenere questo, in futuro, sostenendo che le loro politiche scoraggiano fortemente l'utilizzo std::auto_ptr parametri. Come già detto, IMHO è un punto di vista filosofico e le capacità del framework di derisione non dovrebbero guidare il tipo di interfacce che si desidera progettare o è possibile utilizzare da API di terze parti.

Come già detto, la risposta descrive una soluzione attuabile.

+0

Il thread in questione che hai collegato a talk principalmente sul valore-by 'auto_ptr' è un piano errato (e oh wow, lo è, come lo sono molte cose attorno a 'auto_ptr'): ma la domanda precedente riguarda' unique_ptr', no ? – Yakk

+0

@Yakk Questo perché ho usato 'std :: auto_ptr' nei miei test point reali, ma lo stesso principio funziona anche per' std :: unique_ptr'. Cosa ne pensi, dovrei modificare la domanda di conseguenza? –

+0

Solo questo bit: "questo tipo di utilizzo dei parametri del puntatore intelligente" - il forte scoraggiamento riguarda i parametri di 'auto_ptr', scritti nel 2010 prima dell'esistenza di' unique_ptr'. La modifica del framework in modo che 'auto_ptr' possa essere mal utilizzata è una posizione abbastanza accettabile: farlo dopo che' unique_ptr' è sulla scena è un diverso tipo di pesce. Se si esaminano i motivi per cui essi ignorano 'auto_ptr' come un tipo di parametro ragionevole, non si applicano a' unique_ptr'. – Yakk