How to write unit test for a network client?

I need to write a simple http client. It would be great to have unit tests for my class. But I don’t know how to write a valid and testable class.

For example, I have a client like this:

class HTTPClient { public: HTTPCLient(const std::string& host, const std::string& port): session(host, port) {} void send() { session.sendRequest(someRequest); Response response = session.receiveResponse(); // ... } private: SomeLibrary::ClientSession session; }; 

How to test send method (that I really send what I want)? I can not scoff at it. I can write that the HTTPClient receives the SomeLibrary::ClientSession in the constructor (in the test that I would pass to the layout), but is this a good design? I think a way to implement a session, etc. Gotta hide in my class.

Do you have any ideas?

+7
c ++ unit-testing c ++ 11 googletest gmock
source share
3 answers

I wrote the HTTP client library a long time ago.

To test the HTTP client library, I just wrote a simple test code that started listening on std::thread on some random port on localhost . Then I told the client to make a test request with the host and port parameters, as in your case, pointing to the port that was listening to my stream now. The stream code was programmed to receive a connection, read an HTTP request, save it, and then respond to it using a canned HTTP response.

And how I tested my client library, checking both the actual request sent by the client and how the client handled the complete HTTP response. Later, I developed this unit test code to send various kinds of HTTP errors and incorrect HTTP responses to test and verify how client code handled these situations.

And for a good measure, all this was protected by the alarm() call, so if something got stuck in an infinite loop or so, the whole process would eventually commit suicide.

And how can you check your own code too, too.

+5
source share

Insert an abstract client session instance into the constructor. Discard it in unit tests and pass the real instance at startup to the real one.

You say that you cannot mock him in one sentence, and in the next sentence you say you can - what do you mean? If you mean that the session class is not “yours” or that it cannot be obtained because it was mocked in this way, then you tried to wrap it in your class so that it could be mocked?

In addition, you say: "I think that the way to implement a session, etc. should be hiding in my class."

Your mistake in this assumption is that your class, I think you mean HTTPClient , has nothing to do with it - it is a session class that should hide its own implementation, and that it can do this if you pass its like an instance in a constructor that also adds infinite flexibility in general.

0
source share

you can simulate a simple http server using a socket. The following psuedo code may help:

 1) set up a string to send from the client, take its length in before hand 2) open a new thread with a socket in it 3) bind the socket into some port , listen and accept new connection 4) send the string you have setted with your http client 5) in the socket side, read until the length you saved has reached, save that string for comparison 6) send some pre-defined http response 7) close the socket 7) close the thread 8) continue testing, you have the string which the server got, and the string which the client got, and the original strings which these was originated from 

mimicing chunked transfer and redirections is simple, but SSL fake can be quite complicated. you can wrap your socket with some SSL stream provided by the openSSL stream or Boost SSL stream.

another option is to use an already-written HTTP server on the local host. writing one (for testing only) in Python or Node.js is quite simple and is suitable for this testing task. before running the test, activate the script server (with Node.js script, it's as easy as system("node myServer.js") ), and when the test is complete, destroy this server.

0
source share

All Articles