3
\$\begingroup\$

I have a java based server application that needs to support multiple clients. In the main class I have a method that runs in an infinite loop and waits for client connection. Following is this method:

public void listen() {
    try {
        serverSocket = new ServerSocket(portNo);
        while (true) {
            clientSocket = serverSocket .accept();
            ClientMgr client = new ClientMgr(clientSocket);
            client.start(); //start a separate thread to manage client
        }
    } catch (Exception e) {
        //handle any exceptions
    } finally {
        close(); //close any open sockets
    }
}

I would like to know how I can design (change) this method such that it can be tested by a unit test. If it is already testable then suggest how this can be tested?

\$\endgroup\$
3
\$\begingroup\$

I think it's possible to test this method with another threads and some helper code which passes fix requests to your server and checks the server's answer. It definitely requires some work and I'm not sure how should we call this test: unit test, module test or integration test? Anyway, make sure that the checks happens on the the test method's thread, otherwise JUnit won't detect the uncatched exceptions.

To make it more testable I'd separate the ClientManager creation to an IncomingConnectionHandler interface and implementation and pass an instance of this object to the class of the listen method.

public interface IncomingConnectionHandler {
    void handle(Socket socket);
}

public final class IncomingConnectionHandlerImpl {

    public IncomingConnectionHandlerImpl {
    }

    public void handle(final Socket socket) {
            final ClientManager client = new ClientManager(clientSocket);
            client.start();
    }
}


public class MySocketListener {

    private final IncomingConnectionHandler incomingConnectionHandler;

    public MySocketListener(final IncomingConnectionHandler incomingConnectionHandler) {
        this.incomingConnectionHandler = checkNotNull(incomingConnectionHandler, 
            "incomingConnectionHandler cannot be null");
    }

    public void listen() {
        try {
            serverSocket = new ServerSocket(portNo);
            while (true) {
                final Socket clientSocket = serverSocket.accept();
                incomingConnectionHandler.handle(clientSocket);
            }
        } catch (Exception e) {
            //handle any exceptions
        } finally {
            close(); //close any open sockets
        }
    }

After this in the unit test you could do the following:

  • create a MySocketListener instance with a mocked IncomingConnectionHandler,
  • start an new thread which connects to the port of MySocketListener,
  • check that the handle method of the mocked IncomingConnectionHandler was called with a live/proper Socket instance,
  • shutdown the helper thread and the MySocketListener.

Consider not using using abbreviation like Mgr. It would make the code readable.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.