Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Using Mocks with Networking
Forum Updated to NodeBB v4.3 + New Features

Using Mocks with Networking

Scheduled Pinned Locked Moved Unsolved General and Desktop
5 Posts 2 Posters 2.3k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    mstoth
    wrote on 1 Aug 2017, 13:13 last edited by mstoth 8 Jan 2017, 13:39
    #1

    I have the following system: 1. A 'Messenger' class which is a singleton with the method sendMessageToTcpServer(char const *) which passes a string through a tcp socket to a server running on a different machine. When the different machine sends a message to me over the socket, my messenger class emits a signal called "receivedCPPP(char const *)" with the string as an argument. I have a slot connected to that signal so I can handle it.

    What I want to do is mock the messenger so when I send a specific string, I can tell the mock to emit the signal with the expected response string as an argument without having the different machine attached.

    Here's the test code I have so far. All it does is pretends to make the tcp socket connection. It doesn't really test anything yet.

    class MockMessenger : public Messenger {
    public:
        MOCK_METHOD0(isConnected,bool());
        MOCK_METHOD0(connectToHostServer,void());
        MOCK_METHOD1(sendMessageToTcpServer,void(char const *));
    };
    
    class MockTcpSocket : public QTcpSocket {
    public:
        MOCK_METHOD1(waitForConnected,bool(int));
    };
    
    TEST(TestMessenger,checksConnect) {
        MockMessenger m;
        ON_CALL(m,isConnected()).WillByDefault(Return(true));
    
        EXPECT_CALL(m,isConnected()).Times(1);
        Communicator::Instance()->connectToTcpServer();
        ASSERT_TRUE(m.isConnected());
    }
    
    TEST(TestMessenger,checksTcp) {
        MockTcpSocket s;
        ON_CALL(s,waitForConnected(5000)).WillByDefault(Return(true));
        EXPECT_CALL(s,waitForConnected(5000)).Times(1);
        ASSERT_TRUE(s.waitForConnected(5000));
    }
    
    
    
    int main(int argc, char** argv) {
        QTcpSocket s;
      // The following line must be executed to initialize Google Mock
      // (and Google Test) before running the tests.
      ::testing::InitGoogleTest(&argc, argv);
      ::testing::InitGoogleMock(&argc, argv);
      return RUN_ALL_TESTS();
    }
    
    

    I'm clueless as to how I can make a test suite and be independent of the attached system my code relies on. What can I do to make a test that will let me send a message like "{"mtype":"GIRQ"}" and receive the signal receivedCPPP("Version 1") for instance. Seems like a perfect need for a mock but I'm new to mocks and stubs unfortunately and what I have found so far has not given me enough insight.

    Many thanks for any advice!
    Michael

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 1 Aug 2017, 21:51 last edited by
      #2

      Hi,

      What exactly do you want to know about mocks ? How to implement them ? How to use them ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • M Offline
        M Offline
        mstoth
        wrote on 10 Aug 2017, 14:44 last edited by mstoth 8 Oct 2017, 14:46
        #3

        I guess my confusion is regarding both implementing and using in this case. I want to mock my class so when I send a method a string, my test expects to get a signal with a different string returned. As an example, my class Communicator is a singleton and I send a string to the server like this.

        Communicator::Instance.sendMsgToTcpServer("{\"mtype\":\"GIRQ\"}");

        When this happens, I expect get a signal back from the class called

        receivedGIRQ("Version 1")

        This string, "Version 1", was received in real life by the Communicator class from a tcp socket connected to a real life server. In testing I don't want the server there but I want the mocked Communicator class to act as though it received the message from the server and send the signal whenever I pass it the first string.

        I have seen how to expect a specific number of calls, and specify a return value, but not how to expect a signal with a specific string whenever I call a specific method.

        If it helps, this is the header file for the singleton.

        //your code here
        #ifndef MESSAGER_H
        #define MESSAGER_H
        
        #include <QObject>
        #include "navmessage.h"
        #include <QTcpSocket>
        #include <QTimer>
        #include "singleton.h"
        #include "dialogsplash.h"
        #include "mainwindow.h"
        class MainWindow;
        
        class IMessenger : public QObject {
        public:
            virtual void sendMessageToTcpServer(char const *) = 0;
            virtual void connectToTcpServer() = 0;
            virtual bool isConnected() = 0;
        };
        
        
        class Messenger : public IMessenger
        {
            Q_OBJECT
        public:
            explicit Messenger();
            virtual void sendMessageToTcpServer(char const *) override;
            virtual void connectToTcpServer() override;
            virtual bool isConnected() override;
            virtual ~Messenger() {}
            QTcpSocket *tcpSocket;  // the preset server on the organ
            bool voicingLocked;
            void sendRequest(char const *);
            void connectSeqSignal(MainWindow *);
            void connectDivPistonSignal(MainWindow *);
            QString firstValid;
            QString strmsg,partial,complete;
        
        
        private:
            bool _connected;
            bool            retryPreset;                    //!< true if we should retry connecting to the preset server
            bool            retrySeq;                       //!< true if we should retry connecting to the seq server
            QTimer *        timer;                          //!< timer used for testing/dev't
            bool            hasValidMessages(QString);
            QString         popFirstValidMessage(QString);
        
            static Messenger *m_pInstance;
        signals:
            void receivedGIRP(QVariantMap map);
            void receivedCAPT(QVariantMap map);
            void receivedCPPP(QVariantMap map);
            void receivedGERR(QVariantMap map);
            void receivedSEQR(QVariantMap map);
            void receivedSSTA(QVariantMap map);
            void connectionClosed(QString);
            void messengerError(QString);
            void displayMessage(QString);
            void refreshGVSignal();
            void sequenceStepInfoSignal(QString);
            void sequenceDivisionPistonSignal(QString);
        
        public slots:
            void refreshGVSlot();
            void sequenceStepInfoSlot(QString);
            void sequenceDivisionPistonSlot(QString);
        
        private slots:
        
            //! parses incoming JSON messages from servers; distributes most messages to the active screen
            void readServer();
        
            //! print the error returned when server closes connection
            void connectionClosedByServer();
        
            //! timer callback used for debugging only
            void timeout();
        
            //! slot called on socket errors
            void error(QAbstractSocket::SocketError);
        
            //! slot used for retrying connection attempts (periodic retries while servers starting up)
            void retryConnect();
        
        public slots:
            //! called when server is connected; proceed to another connection, or switch to Splash screen.
            void hostConnected();
        
        private:
        
        };
        
        typedef Singleton<Messenger> Communicator;
        
        #endif // MESSAGER_H
        
        
        1 Reply Last reply
        0
        • S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 10 Aug 2017, 22:16 last edited by
          #4

          Then rather than a QTcpSocket you should have the generic QIODevice.

          Then you can write your MockDevice to answer what you expect and in your code you either set a QTcpSocket when connecting to your real server or your MockDevice if you are testing or just don't have that server available.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • M Offline
            M Offline
            mstoth
            wrote on 11 Aug 2017, 12:41 last edited by
            #5

            ok, i'll look into QIODevice, thanks!

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved