Domanda

Given a class that implements an interface, but does not need all of the methods implemented, what is the best practice for unit testing this class with respect to code coverage? - or is it considered a sign for a code smell?

To make the problem more concrete, consider a Java class (the question is not limited to Java though) that implements ComponentListener but derives from some X (so as to rule out the choice to use ComponentAdapter). The class is however only interested in the componentResized() method and leaves the other callback method bodies empty.

When checking the code coverage, we get a report that indicates correctly that the remaining methods are untested. For obvious reasons, I hesitate to add a test that simply calls a no-op method for the sake of coverage.

While I am not bound to reach a certain coverage, I still think that in and of itself, this phenomenon may indicate a code smell with respect to the single-responsibility principle. On the other hand, it's not far-fetched either that a component representation is responsible for updating its state on a resize.

Is there some sort of consensus or best practice on how to handle such methods, or is the question illegitimate as in it is a result of a supposedly bad design?

È stato utile?

Soluzione

I'm not sure what the best practice would be but to me, your problem isn't a problem of empty interface methods - it's a problem that your interfaces are wrong.

If you implement an interface, implement the entire interface - if the interface is too broad or has functionality that you're not interested in then split the interface and have the main interface implement sub-interfaces and have your component only implement the bit that's appropriate.

Altri suggerimenti

An Interface represents a contract that your implementation class agrees to fulfill. The parts of that contract that you are not interested in, you are still implementing and therefore they still have behavior - the behavior being either do nothing (as I expect in your example) or throwing an UnsupportedOperationException if you are purposefully reducing the scope of the implementation (such as List#Clear).

I think it is still important to a) document the lack of implementation, b) add tests to validate the implementation so that when someone comes along and changes it, your tests break and they have to think a little before modifying your IOnlyCareAboutResizedComponentsListener class.

I would write a test for the interface, which calls all methods and ignores the results (just to check if no exceptions are thrown ant any method). Than you can make your test-class extend this test-class of the interface.

This way you get full coverage.

Michael's answer shares my feeling that it is a design smell in the first place.

If it is an empty callback that gets called at runtime, you should write the test to make sure that nothing happens in that method.

If the method is not implemented and must never be called, you should consider throwing a java.lang.UnsupportedOperationException.

I think a better pattern if you need code coverage is using an abstract factory. The difference between interfaces and abstract classes already has had some discussion on this site. I find this explanation the most relevant for your question.

Are abstract classes / methods obsolete?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
scroll top