2

I'm starting to play with some test-driven development practises, and I'm having issues deciding whether, and if so how, to test this bit of my code.

I've got a class AbstractServer which contains a ServerSocketFactory and ServerSocket:


public abstract class AbstractServer extends Thread {

    ...SNIP...
    //ServerSocket and factory. 
    private ServerSocket ss; 
    private ServerSocketFactory ssf;

    public AbstractServer ( int _port ) { 
        this.port = _port;

        try {
            ssf = ServerSocketFactory.getDefault();
            ss = ssf.createServerSocket(port);
        } catch (IOException e) {
            // Couldn't create ServerSocket, die. 
            System.exit(1);
        }
    } 
    ... SNIP ...

Both the ServerSocket and the ServerSocketFactory are private, and are never exposed outside of this class.

My questions:

  1. Should I be creating tests to check whether or not I actually create the ServerSocket and the ServerSocketFactory? They're private and not exposed from within the class - how much testing is too much testing?

  2. If testing their creation is something I should do, how do I test private, non-exposed (no getter methods) object creation from outside the class? My naive (read: untested) assumption is that I'd create a test class extending AbstractServer; I'd then have to make the things I'm testing for protected, which semi-defeats the purpose of making them private to begin with.

simont
  • 68,704
  • 18
  • 117
  • 136
  • 1
    Pedanticism: it's not really TDD if you write the tests /after/ the class. – millimoose Jun 27 '12 at 00:21
  • @millimoose I wrote the class a few years ago for a homework project. I'm re-writing it with some enhancements and a GUI to play with Swing. I know how I'm implementing it because I have the old code, but I am doing the tests prior to the (re)implementation ;) – simont Jun 27 '12 at 00:25

4 Answers4

1
  1. I don't write unit tests for populating class variables, that is too trivial and, in my opinion, needs no test. I write unit tests to test routines. For example, to make sure my add() method actually adds and my remove() method actually removes (the correct object). If those class variables are for one reason or another not correctly instantiated, then my functional tests will catch this.
  2. As for testing private variables/classes, I would suggest looking at the following answer: https://stackoverflow.com/a/7075965/1201423. The basic notion behind it is: if it's private and you have the need to test it, should it really be private?
Community
  • 1
  • 1
cklab
  • 3,761
  • 20
  • 29
1

First of all, don't think about internal details of a class during unit testing. For your unit test the class under testing is a black box. You have no information about its internal structure. That's the idea of unit testing.

Now, ask yourself a question: What is the functionality your class is exposing? According to your example it creates a server socket and starts listening to it. Now use a unit test as a mean of specifying this functionality (pseudo code):

int port = 12345;
AbstractServer server = new AbstractServer(port) { };
new Socket("localhost", port);

That's it. This test explains how your class works and what it does. When/if the class ceases to provide that functionality - the test will fail and indicate you about it. That's exactly what the test is for.

yegor256
  • 102,010
  • 123
  • 446
  • 597
0

You don't really need to test this simple constructor specifically. There is only two calls - both of which are to publicly accessible methods and can be tested to make sure they work in their own right. Even in a more complex constructor situation, a builder pattern should be used which would be testable.

As for how much is too much, I sometimes might end up loosening encapsulation a little to make things easier for testing but it really depends on the situation. Generally, as long as you thoroughly test your public api you can be confident that all of the code in the module is working correctly - if the public api works completely then there should be no problems with any of the private code making it happen.

Here is decent article on tdd in some tougher areas to cover: here

grinch
  • 804
  • 1
  • 9
  • 17
0

First of all testing abstract classes is not a good idea. You should test the concrete implementations. The abstract class is just a way of removing the code duplication (via IS-A relationship), you can remove duplication in many other ways (for example one I prefer is HAS-A relationship).

Looking at your code and your question a good starter for you might be this video: How to Write Clean, Testable Code . It will tell you why the approach you took might not be a good idea and will point you to some sample solutions.

Generally: specify scenarios/functionalities you class delivers. Don't test for implementation details.

Good source of knowledge for beginners as well is this: Test Driven Development Blog. Take a look at the older posts in there.

EDIT: If you want to test legacy code there is also pattens for that. In that case the general rule is to start with acceptance, not unit tests.

Wojtek B.
  • 927
  • 2
  • 9
  • 17