aspose file tools*
The moose likes Testing and the fly likes JUnit and Sockets Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Engineering » Testing
Bookmark "JUnit and Sockets" Watch "JUnit and Sockets" New topic
Author

JUnit and Sockets

Timothy Frey
Ranch Hand

Joined: Jul 22, 2006
Posts: 56
I wrote a very small client-server application that uses sockets and I'd like to write some programmer tests with JUnit. I did a quick search on this forum but the only relevant post was from 3 years ago and didn't provide much in the way of answers.

Is there a specific strategy to use when testing socket code? Ideally I think I would like to create a MockSocket object that I can use to explicitly send specific messages to, say, my Client to verify that the Client receives them. Similarly, when the Client sends something to the mock Server, I'd like to have a method where I can check the message received from the Client.

I thought I was on the right track for a while but ran into some problems with my implementation. Specifically, I think my read and write tests were OK but I was getting strange NullPointerExceptions when trying to shutdown the Client and verifying that everything was closed and disconnected.

Anyway, I don't think I need an exact implementation (though it would be nice), but a general strategy or even a point in the right direction would be most helpful. Thanks!
Lasse Koskela
author
Sheriff

Joined: Jan 23, 2002
Posts: 11962
    
    5
The java.net.Socket API is riddled with the final keyword, which makes creating mock implementations next to impossible--without using another interface to wrap the actual Socket. One option is to adopt the alt.java.net package.

Also, taking the idea to use another interface a bit further, network connections can usually be abstracted into one of event sources or streams. You might want to consider abstracting your sockets into a pair of streams (say, "com.company.utils.net.StreamPair")--an interface which you can mock in most of your tests. You can then write only a handful of tests for the implementation of that interface, using actual java.net.Sockets (and ServerSockets).


Author of Test Driven (2007) and Effective Unit Testing (2013) [Blog] [HowToAskQuestionsOnJavaRanch]
Timothy Frey
Ranch Hand

Joined: Jul 22, 2006
Posts: 56
Can you elaborate a little more on this StreamPair interface idea? I kind of get where you're going but I'm not quite there yet.

On the other hand, would this be one of those things that's "too simple to break?" Maybe I should just write a test to make sure my message is being constructed correctly and just assume that the Socket stuff works? After all, the only thing that I'm doing is writing to message to the output stream. Right now I'm basically just using this project for learning purposes; it's very simple so "standard" debugging techniques would work but I am interested in planning for the future. How is Socket stuff tested in the real world?
Lasse Koskela
author
Sheriff

Joined: Jan 23, 2002
Posts: 11962
    
    5
Originally posted by Timothy Frey:
Can you elaborate a little more on this StreamPair interface idea? I kind of get where you're going but I'm not quite there yet.

What I'm after is something like this:


Does this explain further what I'm thinking of?

Originally posted by Timothy Frey:
On the other hand, would this be one of those things that's "too simple to break?" Maybe I should just write a test to make sure my message is being constructed correctly and just assume that the Socket stuff works? After all, the only thing that I'm doing is writing to message to the output stream. Right now I'm basically just using this project for learning purposes; it's very simple so "standard" debugging techniques would work but I am interested in planning for the future. How is Socket stuff tested in the real world?

Well, it's good to have only one piece of your code base do the socket stuff. That way, the one extremely nasty bug you find in your socket code one day is in just one place rather than all over.

In practice, I'd recommend abstracting the actual socket stuff using something like the StreamPair concept above and then write just a handful of tests for the actual socket-based implementation by actually creating ServerSockets and letting the two communicate. Those are darn verbose and complex tests but they're pretty darn important considering that a bug in the way your software handles connections is often of the fatal sort regarding the system's overall availability...
Timothy Frey
Ranch Hand

Joined: Jul 22, 2006
Posts: 56
Wow! Thanks for taking all of that time to answer my question!

Fortunately, I had enough sense to limit the Socket stuff to one very small section of code, so switching Sockets with StreamPairs was very painless. Plus, I was able to create a set of mock objects that allowed me to test the behaviors that I wanted to test. Specifically, I created a MockStreamPair which behaves like a connected Socket and a BadStreamPair which will throw an IOException during construction.

I'm pretty happy with the way these tests turned out. I'm even happier that I was able to test this part of my code when a week ago I thought it was untestable. I owe it all to you (though maybe my new books, Fowler's "Refactoring" and JUnit Recipies, helped a little ). Anyway, thanks again!
Lasse Koskela
author
Sheriff

Joined: Jan 23, 2002
Posts: 11962
    
    5
You're most welcome and I'm glad that you're feeling good about your solution!
Timothy Frey
Ranch Hand

Joined: Jul 22, 2006
Posts: 56
I hate to dig this up again but I've run into some more problems. At first I was just sending plain text across the socket connection. Now, however, I want to send Objects across. Not following the TDD mantra, I wrote the actual code first and everything looks OK to me. I'm basically sending a "DataPacket" object that contains a header (which takes the form of an enum) and a "payload" which can be any type of object.

The testing method described above works great when creating a PrintWriter using the mock output stream but doesn't work when using an OutputObjectStream. If I look at the bytes written to the OutputStream (using the getInput() method described above), it looks like there are a few extra bytes tacked onto the beginning. This is preventing me from comparing the Object I send into the stream to the Object that would show up on the other side.

So far I've been testing only with Strings because it's easy to get the byte array from them (using getBytes()). Basically, I guess I need a way to figure out what the serialized form of any given object takes so I can compare it to what shows up in the OutputStream of my Mock object. Any ideas?
Timothy Frey
Ranch Hand

Joined: Jul 22, 2006
Posts: 56
Sorry for the double post but I found a solution to my problem and I just want to document it in case someone else runs into the same problem.

I just realized that I can deserialize the object but creating an ObjectInputStream out of the bytes written to the output stream:




So simple I feel stupid for not stumbling upon it earlier!
[ August 06, 2006: Message edited by: Timothy Frey ]
Jeanne Boyarsky
author & internet detective
Marshal

Joined: May 26, 2003
Posts: 30752
    
156

Thanks for posting the correct solution.

I'm kicking myself - I thought I posted to use ObjectInputStream the first time I saw this thread. Apparently, I forgot to press submit. Sorry!


[Blog] [JavaRanch FAQ] [How To Ask Questions The Smart Way] [Book Promos]
Blogging on Certs: SCEA Part 1, Part 2 & 3, Core Spring 3, OCAJP, OCPJP beta, TOGAF part 1 and part 2
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: JUnit and Sockets