Reputation: 829
I'm looking for help on now to use TDD for a real world example. Most show are too simple and don't really show how test and re-factor more complicated classes. Here is an example of code that uses both a thread and a network socket. Could someone explain how to create a isolated Unit Test for such a class? Thanks.
public class BaseHandler extends Thread {
protected Socket mClientSocket;
protected BufferedReader is = null;
protected BufferedWriter os = null;
private Logger mLogger = Logger.getLogger(WebTestController.class.getName());
protected WebTestController mWebTestController;
/*********************************************************************
*
* @param piPort - int port to listen on
*/
public BaseHandler(){
}
/*********************************************************************** cleanup
* Ensure sockets are closed as to not run into bind errors
*/
protected void cleanup() {
try {
if (is != null)
is.close();
if (os != null)
os.close();
if (mClientSocket != null)
mClientSocket.close();
}
catch (IOException e) {
e.printStackTrace();
}
mLogger.info("cleaning up a socket");
}
/***********************************************************************************
* Sends a message to the current socket
* @param pMessage
*/
protected void writeToSocket(String pMessage){
try {
os = new BufferedWriter(
new OutputStreamWriter(mClientSocket.getOutputStream()));
}
catch (IOException e) {
e.printStackTrace();
cleanup();
return;
}
try {
os.write(pMessage, 0, pMessage.length());
os.flush();
}
catch (IOException e) {
e.printStackTrace();
}
cleanup();
}
}
Upvotes: 7
Views: 672
Reputation: 237
This class doesn't respect SRP(Single Responsibility Priciple). Your class does too much logic. Instead you should split this class into multiple smaller ones. You usually then inject those classes with Spring or other IoC framework.
If you were to split the class you would notice that it will be much easier to test. You could supply mock objects for those components and inject them as you wish in each test case, as it suits you best.
Upvotes: 1
Reputation: 26856
Here's a couple of practical things to do to reduce your testing issues:
However I strongly recommend reading a good book about TDD and unit testing. The simple tutorials are just that - simple. They don't cover the complicated cases that you will run into in real life. It's perfectly possible to use TDD in real life, but it does take some knowledge - just like programming.
Upvotes: 5
Reputation: 7194
The code doesn't "use" a thread, it's just a class derived from java.lang.Thread
. Nothing stops you from calling the run()
method directly, after all you're testing your class and not the functionality in java.lang.Thread
.
In fact you want to test the cleanup()
and writeToSocket
methods, so there's no need to call the run()
method either.
Just create a subclass of BaseHandler
, initialize your members in that subclass with some mock objects and you're good to go.
You may need other changes to make the rest of your code easier to test, though. I'm assuming this question is more about unit testing an existing code base and less about TDD.
Upvotes: 1
Reputation: 242686
Don't create such classes.
It would be better to break your logic into IO-related part and concurrency-related part. Then IO-related part can be tested, for example, with a mock socket implementation.
Testing concurrency-related logic would be more complex, though. It depends on behaviour you want to achieve.
Upvotes: 5
Reputation: 533520
AFAIK you should start with the Test case in Test Drive Development. I suggest you start with the test this class should pass first and treat this as a prototype.
You will have to create a class or sub-class which will open a Socket to a dummy ServerSocket and send messages to it.
Upvotes: 1