Java Unit Is Evil

I assert that JavaUnitIsEvil because I'm a TellDontAsk kind of developer. Now don't get me wrong I'm completely in favour of test driven development. I'm just absolutely convinced that JavaUnit is not the right tool to exploit this strategy. It offers a FinePromise? but delivers a DeadEnd. JavaUnit encourages perhaps even forces developers to violate the spirit of encapsulation and the LawOfDemeter.

All too often I see JUnit tests like the following, and despair.

  public void testGetSetProperty() {
    setProperty( 10 );
    assertEquals( 10, getProperty() );
  }

-- MartinSpamer

I don't see how that's a fault of JUnit. If you don't like tests like that, don't write tests like that. Write the tests you really need. If the relevant property is used at all, it will be employed in the context of other tests, and hence tested implicitly.

I do write the tests I really need which is why I don't use JavaUnit. However I do find that most JUnit tests are written like that. JavaUnit tests like this require the tested class to expose its internal implementation. JavaUnit tests therefore redefine the shape of the Class's interface. That is what 'I find Evil'.

JUnit tests only "require" the tested class to expose its internal implementation if a naive developer uses it that way. There is nothing in JUnit that stops you from writing tests like the following:

 @Test
 public void testSplork() {
    Splork classUnderTest = new Splork();
    classUnderTest.runTestOfInternalStuff();
    assertEquals(10, classUnderTest.getTestResult());
 }
Presumably, such test methods (or some equivalent) would need to exist regardless of what testing framework you use. Unless there's some characteristic unique to JUnit that you haven't mentioned, I don't see why JUnit would be more evil than anything else.

The testSplork example fails the HollywoodPrinciple and is not semantically different from the testGetSetProperty example.

It is semantically different, because it does not expose any internal structure of Splork except for the test method itself (plus getTestResult()), which can hide a series of internal tests. Thus, it is a single point of contact with a very specific (i.e., test) purpose, so it does not encourage excessive coupling. The testGetSetProperty example implies exposure of internal attributes in order to support external tests, which does encourage excessive coupling and effectively violates encapsulation.

If this is a problem, what do you suggest as an alternative?

As for failing the HollywoodPrinciple, what alternative do you propose? That every class implement a setTestHarness(...) method, or implement a Testable interface?

Use MockObjects. That's exactly what they're designed for. For Java you can use jMock: http://www.jmock.org.


CategoryEvil


EditText of this page (last edited May 3, 2008) or FindPage with title or text search