javajunitparameterized-tests

Enforcing that a JUnit subclass test overrides a @BeforeClass method


I have what amounts to a lightweight test framework written as a JUnit Abstract test. What I would like to do is have the implementing subclasses each define their custom test class setup. My plan was to have the abstract superclass define an @BeforeClass method that calls into an abstract setup method that each subclass would be forced to define, but this fails as the @BeforeClass methods must be static and static methods cannot be made abstract nor can they call instance methods.

I could just assume that subclasses will do the setup by including what's required in the documentation or by throwing an IllegalStateException, but I'd really like to be able to enforce this at an interface level for a number of reasons. Can anyone think of a work around for this?

By the way, I had the same issue with making these tests parameterized (subclasses define the parameters, but @Parameters annotated methods must be static). I got around this by running with the 3rd party JUnitParams runner which allows method level parameters. Check it out here: https://github.com/Pragmatists/JUnitParams


Solution

  • One option is to have subclasses implement a, say, static doSetupOnce() method, and find and invoke that method reflectively from the base class @BeforeClass method. Since this needs to be a static method, its existence can only be enforced at runtime.

    Another approach would be to have an abstract doSetupOnce instance method in the base class which gets invoked the first time the parent's @Before method gets invoked. This enforces the issue at compile time, but then implementors will have to be careful not to access instance fields from this method (since this is probably not what they want).

    In general (and without knowing the details of your situation), I'm not very fond of either of these approaches, and would rather leave it up to implementors to declare a @BeforeClass method if needed. Locking them up in a rigid base class scheme can cause more problems than it solves. Also consider the use of JUnit rules, which often are a better choice than base classes (e.g. because they are composable). Of course you can also combine the two approaches, relying mainly on JUnit rules and additionally offering some base classes with predefined rules for convenience.