views:

1067

answers:

4

Before asking question, let me explain the current setup:

I have an service interface, say Service, and one implementation, say ServiceImpl. This ServiceImpl uses some other services. All the services are loaded as bean by spring.

Now, I want to write junit test cases for the ServiceImpl. For the same, I use the applicationContext to get the Service bean and then call different methods on it to test them.

All looks fine for the public methods but how do I write test cases for private methods? Because we might not have the same private methods for different implementations?

Can anyone help me here on what should be preferred way of writing test cases?

A: 

I think you should split the testcases.

First you test the class which is calling the different implementations of the interfaces. This would mean you are testing the public methodes.

After this you test the interface implementaion classes in another testcase. Their you can call the methode with reflection.

Markus Lausberg
+3  A: 

Private methods should be exercised through the public interface of a class. If you have multiple implementations of the same interface, I'd write test classes for each implementation.

moffdub
A: 

I found an interesting article on how to test private methods with JUNIT at http://www.artima.com/suiterunner/privateP.html

So, I assume we should prefer testing private methods indirectly by testing the public methods. Only in exceptional circumstances, we should think of testing private methods.

Jagmal
That article is **horrible**. Approach 1 is the only valid answer - yet somehow the author insists he agrees with the advice not to test private methods but does it anyway.Either his utility methods should be moved into their own class and made public, or they're tested by existing class tests.
Andrzej Doyle
@dtsazza: I agree that approach 1 is probably the best way. But, you should give credit to the author to try out different approaches and came up with a good article for the same. Also, by doing so, he proves a point that approach 1 is probably the best.
Jagmal
+1  A: 

The purist answer is that private methods are called that for a reason! ;-)

Turn the question around: given only the specification of a (publicly-accessible) interface, how would you lay out your test plan before writing the code? That interface describes the expected behavior of an object that implements it; if it isn't testable at that level, then there's something wrong with the design.

For example, if we're a transportation company, we might have these (pseudo-coded) interfaces:

CapitalAsset {
    Money getPurchaseCost();
    Money getCurrentValue();
    Date  whenPurchased();
    ...
}

PeopleMover {
    Weight getVehicleWeight();
    int    getPersonCapacitly();
    int    getMilesOnFullTank();
    Money  getCostPerPersonMileFullyLoaded(Money fuelPerGallon);
    ...
}

and might have classes including these:

Bus implements CapitalAsset, PeopleMover {
    Account getCurrentAdvertiser() {...}
    boolean getArticulated() {...}
    ...
}

Computer implements CapitalAsset {
    boolean isRacked() {...}
    ...
}

Van implements CapitalAsset, PeopleMover {
    boolean getWheelchairEnabled() {...}
    ...
}

When designing the CapitalAsset concept and interface, we should have come to agreement with the finance guys as to how any instance of CapitalAsset should behave. We would write tests against CapitalAsset that depend only on that agreement; we should be able to run those tests on Bus, Computer, and Van alike, without any dependence on which concrete class was involved. Likewise for PeopleMover.

If we need to test something about a Bus that is independent from the general contract for CapitalAsset and PeopleMover then we need separate bus tests.

If a specific concrete class has public methods that are so complex that TDD and/or BDD can't cleanly express their expected behavior, then, again, that's a clue that something is wrong. If there are private "helper" methods in a concrete class, they should be there for a specific reason; it should be possible to ask the question "If this helper had a defect, what public behavior would be affected (and how)?"

For legitimate, inherent complexity (i.e. which comes from the problem domain), it may be appropriate for a class to have private instances of helper classes which take on responsibility for specific concepts. In that case, the helper class should be testable on its own.

A good rule of thumb is:

If it's too complicated to test, it's too complicated!

joel.neely