2011-09-30 8 views
37

Tengo una fábrica que devuelve un puntero inteligente. Independientemente del puntero inteligente que utilice, no puedo hacer que Google Mock se burle del método de fábrica.¿Puede Google simular un método con un tipo de retorno de puntero inteligente?

El objeto simulado es la implementación de una interfaz abstracta pura donde todos los métodos son virtuales. Tengo un prototipo:

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

Y consigo:

"...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>'" 

El tipo señalado en el se define el puntero inteligente.

Y entiendo que está tratando de acceder a uno de los constructores declarados privados, pero no entiendo por qué. Cuando esto era un std :: auto_ptr, el error decía que no había un constructor de copia, lo cual me confunde.

De todos modos, ¿hay alguna manera de simular un método que devuelve un puntero inteligente? ¿O hay una mejor manera de construir una fábrica? ¿Mi única determinación es devolver un puntero sin formato (blech ...)?

Mi entorno es Visual Studio 2010 Ultimate y Windows 7. No estoy usando CLI.

Respuesta

-1

Google Mock requiere que los parámetros y los valores devueltos de los métodos simulados sean copiables, en la mayoría de los casos. Por boost's documentation, unique_ptr no se puede copiar. Tiene la opción de devolver una de las clases de punteros inteligentes que utilizan la propiedad compartida (shared_ptr, linked_ptr, etc.) y se pueden copiar. O puede usar un puntero sin formato. Como aparentemente el método en cuestión es el método para construir un objeto, no veo ningún problema inherente al devolver un puntero sin formato. Siempre que asigne el resultado a un puntero compartido en cada sitio de llamada, estará bien.

+31

No debería necesitar hacer ningún cambio en las interfaces de sus clases solo para que funcionen con su estructura de simulación.A menudo, esto no es posible en absoluto. ¡Esta no es una solución aceptable para mí! –

+12

No me parece aceptable que una clase de fábrica devuelva un puntero sin formato. En este caso, unique_ptr tiene más sentido. Fue diseñado en parte para resolver el problema de "asignar el resultado a un puntero compartido en * cada * sitio de llamadas". –

+3

No creo que esta sea la respuesta correcta, cambiar todo a propiedad sin procesar o compartida no es una solución solo para probar cosas. – paulm

78

Una solución factible para los problemas de google mock framework con los argumentos de la función non (const) que pueden copiarse y los valores de restauración es usar métodos proxy mock.

Suponga que tiene la siguiente definición de interfaz (si se trata de un buen estilo para usar std::unique_ptr de esta manera parece ser más o menos una cuestión filosófica, personalmente me gusta hacer cumplir transferencia de la propiedad):

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

la clase simulacro apropiada podría definirse así:

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*()); 
}; 

Sólo tiene que tener cuidado, que las configuraciones (las medidas tomadas) para el retorno nonCopyableReturnProxy() método de cualquiera NULL o un instanc e asignado dinámicamente en el montón.


Hay una google-mock user forum thread la discusión de este tema en el que uno de los mantenedores afirma que el marco Google de forma simulada no se cambiará para apoyar esto en el futuro el argumento de que sus políticas desaconsejan el uso std::auto_ptr parámetros. Como se mencionó, este es en mi humilde opinión un punto de vista filosófico, y las capacidades del marco burlón no deben dirigir qué tipo de interfaces quieres diseñar o puedes usar de API de terceros.

Como dije la respuesta describe posible solución.

+0

El hilo en cuestión al que vinculó para hablar principalmente sobre 'auto_ptr' by-value es un mal plan (y oh wow, es así, como lo son casi todas las cosas que rodean' auto_ptr'): pero la pregunta anterior es sobre 'unique_ptr', no ? – Yakk

+0

@Yakk Eso es porque he estado usando 'std :: auto_ptr' en mis cajas de prueba reales, pero el mismo principio también funciona para' std :: unique_ptr'. ¿Qué piensas, debería editar la pregunta en consecuencia? –

+0

Solo este bit: "este tipo de uso de parámetros de puntero inteligente": el fuerte desaliento se trata de parámetros 'auto_ptr', escritos en 2010 antes de la existencia de' unique_ptr'. La modificación del marco para que 'auto_ptr' pueda ser mal usado es una posición bastante aceptable: hacerlo después de que' unique_ptr' esté en la escena es una olla de pescado diferente. Si examina los motivos por los que rechazan 'auto_ptr' como un tipo de parámetro razonable, no se aplican a' unique_ptr'. – Yakk

Cuestiones relacionadas