Thursday, November 10, 2005
Junit on private methods
Sometimes, I want to write JUnit tests for private methods. I think it's legitimate to want to do this - especially if I'm writing the test first.
The options according to Bill Venners are:
1. Promote them to protected.
No, I agree with Bill that this is definitely *dirty*.
2. Use that 'PrivateAccessor.invoke' thing from junit-addons.
I don't like this. For one, I can't remember the syntax, for two, I can't bare to look at it it's so ugly. Passing method names as strings - Urrrch.
3. Put my tests inside the classes they test
No, that will make them too big, and I don't like scrollbars either.
4. Deny that I want to test them after all.
This is my boss Leigh's view. But I am unconvinced....
Here are some arguments for it:
Argument 1: if something is interesting and complex enough to be worthy of testing, then it should be moved into a new class and become public. (This is the JUnit official line too.)
But what about this:
- doChecksum does not belong in its own class, and does not need to be more public. But I do really want to test it. Not testing it will make me worry.
Argument 2: A complete enough suite of tests on public/protected/package scoped methods will end up testing all paths through the code anyway.
- True, BUT:
1. It's harder work to set up the test.
What about this:
2. It's harder to understand the test later.
I am a simple creature - i want tests for foo() to be called testfoo...(), and in them, I want to see calls to foo().. What's wrong with that? Life is hard enough.
The solution: ?? Hmm..
1. Sun magically deal with it.
2. Put tests inside testee classes - but get IDE to hide them. Ie, eclipse & co. magically deal with it.
3. ???
The options according to Bill Venners are:
1. Promote them to protected.
No, I agree with Bill that this is definitely *dirty*.
2. Use that 'PrivateAccessor.invoke' thing from junit-addons.
I don't like this. For one, I can't remember the syntax, for two, I can't bare to look at it it's so ugly. Passing method names as strings - Urrrch.
3. Put my tests inside the classes they test
No, that will make them too big, and I don't like scrollbars either.
4. Deny that I want to test them after all.
This is my boss Leigh's view. But I am unconvinced....
Here are some arguments for it:
Argument 1: if something is interesting and complex enough to be worthy of testing, then it should be moved into a new class and become public. (This is the JUnit official line too.)
But what about this:
public class ISSN{
public ISSN(String issn){
validate(issn);
// other stuff
}
private void validate (String issn) throws Exception{
removeHyphen(issn);
doChecksum(issn);
}
private void doChecksum(String issn) throws Exception{
// tricky looping and chopping stuff here
// only 8 lines though
}
....
- doChecksum does not belong in its own class, and does not need to be more public. But I do really want to test it. Not testing it will make me worry.
Argument 2: A complete enough suite of tests on public/protected/package scoped methods will end up testing all paths through the code anyway.
- True, BUT:
1. It's harder work to set up the test.
What about this:
public class ISSN{
public ISSN(String issn, SomethingInconvenientToCreate foo){
validate(issn);
// other stuff
}
...
2. It's harder to understand the test later.
I am a simple creature - i want tests for foo() to be called testfoo...(), and in them, I want to see calls to foo().. What's wrong with that? Life is hard enough.
The solution: ?? Hmm..
1. Sun magically deal with it.
2. Put tests inside testee classes - but get IDE to hide them. Ie, eclipse & co. magically deal with it.
3. ???