es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cómo utilizar gmock SaveArgPointee con std::shared_ptr de una clase derivada.

Tengo una clase BaseMessage de la cual derivan varias subclases diferentes de DerivedMessage y quiero enviarlas de esta manera:

class BaseMessage {
public:
   virtual std::vector<uint8_t> data() const noexcept = 0;
   virtual ~BaseMessage() = default;
   [...]
}

class DerivedMessage : public BaseMessage {
public:
   [...]
   std::vector<uint8_t> data() const noexcept override { return m_data; }
private:
   std::vector<uint8_t> m_data;
}

// simplificado 
class Tcp {
public
   virtual void sendMessage(std::shared_ptr<BaseMessage> msg) { write(msg->data());}
   [...]
};

class SomeClass {
public:
   SomeClass(Tcp& tcp) : m_tcp(tcp) {}
   void writeDataToRemote(std::shared_ptr<DerivedMessage> derived) const {
      m_tcp.sendMessage(derived);}
private:
   Tcp m_tcp;
}
};

Ahora quiero escribir pruebas para la clase SomeClass con gtest.

Por lo tanto, simulo la función de la clase TCP:


class MockTcp : public Tcp {
MOCK_METHOD(void, sendMessage, (std::shared_ptr msg), (override));
[...]
}

Supongamos que todo está simplificado hasta aquí pero funciona.

Entonces, en la prueba, me gustaría examinar el argumento dado a sendMessage en la función writeDataToRemote.
He leído sobre ::testing::SaveArg y ::testing::SaveArgPointee en StackOverflow (pero no en la documentación, sin embargo).

TEST(SomeClassTest, writesMessageToSocket){
   MockTcp mockTcp;
   SomeClass sc(mockTcp);

// >>>¿cómo declarar msgArg aquí?<<<
   EXPECT_CALL(mockTcp, sendMessage()).Times(1).WillOnce(::testing::SaveArgPointee<0>(msgArg));
   const auto derivedMsg = std::make_shared<DerivedMessage>();
   sc.writeDataToRemote(derivedMsg);
   // sigue una inspección posterior de msgArg
}

Como se escribe en el comentario del código, no sé cómo declarar la variable msgArg para que pueda recibir el argumento real dado a sendMessage. Cuando uso SaveArg, creo que obtendría un puntero colgante y al hacerlo como se indica arriba, obtengo errores porque el mensaje no se puede copiar-asignar. Cualquier sugerencia sería apreciada.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para declarar la variable msgArg para que pueda ser asignada al argumento real dado a sendMessage, se puede utilizar la función SaveArgPointee proporcionada por GoogleMock.

    Aquí hay un ejemplo de cómo se puede modificar la prueba para declarar msgArg:

    TEST(SomeClassTest, writesMessageToSocket){
       MockTcp mockTcp;
       SomeClass sc(mockTcp);
    
       std::shared_ptr<basemessage> msgArg;
       EXPECT_CALL(mockTcp, sendMessage(_)).Times(1).WillOnce(::testing::SaveArgPointee<0>(&msgArg));
       const auto derivedMsg = std::make_shared<derivedmessage>();
       sc.writeDataToRemote(derivedMsg);
    
       // further inspection of msgArg follows
    }
    

    Este código declara msgArg como std::shared_ptr<basemessage>, que es el tipo de argumento que sendMessage espera. Luego, en la declaración EXPECT_CALL, SaveArgPointee<0>(&msgArg) guarda un puntero al objeto apuntado por el primer argumento de la función simulada en msgArg.

    Tenga en cuenta que SaveArgPointee toma un puntero a la variable donde se debe guardar el argumento. Aquí, proporcionamos &msgArg para obtener su dirección.

    Después de que la prueba se completa, se puede inspeccionar el objeto apuntado en msgArg para verificar que se haya enviado el DerivedMessage correcto.

Comments are closed.