Enforcing that a JUnit subclass test overrides a #BeforeClass method - java

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

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.

For your main question, why not make your parent class abstract and use the #Before annotation instead of #BeforeClass ? For example:
public abstract class TestParent {
#Before
public void setup() {
doSetup();
}
protected abstract void doSetup();
// other stuff...
}
public class RealTest extends TestParent {
protected void doSetup() {
// custom setup
}
// custom tests...
}
This will force the subclasses to redefine the doSetup() method without using static methods.

This may be out of scope or overkill, but I think it's worth mentioning since they're not that different. So I'm taking a leap of faith and suggest that you could try TestNG because methods annotated with #BeforeClass do not have to be static, nor do those annotated with #Parameters.
You can read about the differences between the 2 frameworks here and it looks like they also have support for migrating JUnit tests to TestNG

I don't think it is possible to do this in a clean OO way. Not only is #BeforeClass a static method, but JUnit will call the parent's #BeforeClass before the child's #BeforeClass.
Anyway you try to do this must necessarily expose the parent class's internal static state so a child class can set the parent's fields, breaking encapsulation.
I think the best way is to to use #Before, but also have a static flag that sets if the method has been called before, that way at least you can short circuit and only do the initialization for the first call...

Related

java - Allow extending static method in sub classes

Using JUnit all my runner classes implement a method that is annotated with
#BeforeClass
public static void setUp() throws Exception {}
There is a lot of mutual code.
I want to create a base runner that will hold all the base code and will allow sub classes to add more features.
This is all static. What is the best practice?
You should reconsider your design. The #BeforeClass annotation is intended to specify code that has to run exactly once for all tests. If you repeat the same code in multiple static methods annotated with #BeforeClass, in other words, execute the same action multiple times, it suggests that it is not the #BeforeClass semantic that you want.
Maybe you just want instance methods annotated with #Before
Otherwise, if it’s really about single time actions, just put a static method with the #BeforeClass annotation into the base class, and you’re done. The initialization of the subclass implies the initialization of the base class. The initialization of the base class will happen exactly once for all subclasses but that is what #BeforeClass is all about. As said, if you want an initialization once per subclass or once per test, it’s more likely that #Before is the feature you want.
Note further, that you can have code in static methods in a base class which is only executed when subclasses invoke it. Just place the code into a method without the #BeforeClass annotation. Then, methods in subclasses, having the annotation or not, may invoke the method of the base class. There is no need for an override relationship here.
As said; there is no "overriding" for static; and of course: static is by itself ... very often an indication for "design improvement required". Everybody who is writing serious unit tests knows that static things can make unit testing a night-mare. So we avoid static in our production code. But then, in our testing code, we just use it?!
And going one step further: some people claim that inheritance is not a good answer to "i have a lot of common code within my unit tests".
See here for example.
You could move the common code to a rule and reuse that rule in every test: https://github.com/junit-team/junit/wiki/Rules

How to require that JUnit tests implement a #BeforeClass/#AfterClass "abstract method"?

As a heavy TestNG user, this is not a problem, since #{Before,After}Class methods are not static...
But in JUnit, they are.
And this is quite a problem for what I am currently doing.
I am writing assertions for java.nio.file.Path for assertj, which uses JUnit 4.x for tests. Some assertions require that I initialize a FileSystem (a memoryfs to be precise) to test them; such a filesystem should, ideally, be initialized at the test class level and not per test. And depending on the test class, I need to initialize the contents of that filesystem differently.
Right now however, I use #Before/#After since I don't know better...
Again, with TestNG, not a problem, since #{Before,After}Class are not static. So, how do you do this with JUnit?
.
You can create a rule class for your initialization:
public class Resource extends ExternalResource {
protected void before() {
// ...
}
protected void after() {
// ...
}
}
and then reference it in each test:
#ClassRule public static Resource resource = new Resource();
Any per-test customisation can be done by making resource an anonymous inner class and
overriding methods, or passing parameters to its constructor.
If you have a common base class, you can put resource in there, and then only declare it in subclasses that need to customize it. In junit, class rules in subclasses will override class rules in a parent class with the same name.

Junit protected method

I'm wondering about a nice way to deal with a protected method in Junit.
Assuming I want to test a class called A which has a protected member and constructor.
I understood that in order to test the class A I should write another class called ATest which might extend TestCase ( this should be mandatory in Junit3 ). Because I want to test a protected method and because A has a protected constructor, my test class ATest should also extend the class A where that method is implemented in order to be able to create that class and to access to the method.
could be a double inheritance from both classes a nice solution?
P.S I've already Known that in Junit 4 the inheritance from the TestCase might be avoided.
To gain access to A's protected members, you can just put A and ATest in the same package.
Java doesn't allow multiple inheritance of implementation. You can implement multiple interfaces.
I would prefer using reflection to get at methods for testing that I don't want clients to know about. Works for private methods, too.

Is there a 'new' modifier for methods in Java?

Is there an equivalent to C#'s new modifier in Java?
I'd like to use it for unit tests - every init() method should be marked final and annotated with #Before. Then, jUnit executes all of these init() methods.
I don't want to bother coming up with new names for each of these init() methods, and I definitely wants to mark them as final to make sure they don't override eachother (an alternative pattern is to override and call super.init() from every init() method).
A common pattern is to make your own 'before' methods final and create protected (abstract) methods for the subclasses.
In the superclass
#Before
public final void before() {
onBefore();
}
protected void onBefore() {
}
In the subclass
protected void onBefore() {
// prepare the test fixture
}
This gives you the best of both worlds:
a well-known method to override in sub-classes;
overriding is optional;
the superclass method is never overriden;
the client method is invoked when the super-class decides, i.e. either before or after the super-class decides.
It does have a single downside - it ties you to a single super-class. Still, that may not be an issue to your environment.
Unfortunately not. Heck, before #Override there wasn't even any way of protecting against typos when overriding.
You can't create a method with the same signature as a superclass method without it overriding that method. Admittedly I try not to do this even in C#...
Have you considered using initFoo and initBar for classes Foo and Bar respectively (etc)? It's a simple enough pattern to follow, and would avoid the name collisions. A bit ugly, admittedly.
Java does not have an equivalent to the C# new operator which is
Used to hide an inherited member from a base class member.
For what you'd like to do, why not create a base class that your other tests can extend, and create an abstract method named init() (marked with #Before) in the base class? This forces all subclasses to supply an init() method.

How to unit test abstract classes: extend with stubs?

I was wondering how to unit test abstract classes, and classes that extend abstract classes.
Should I test the abstract class by extending it, stubbing out the abstract methods, and then test all the concrete methods? Then only test the methods I override, and test the abstract methods in the unit tests for objects that extend my abstract class?
Should I have an abstract test case that can be used to test the methods of the abstract class, and extend this class in my test case for objects that extend the abstract class?
Note that my abstract class has some concrete methods.
There are two ways in which abstract base classes are used.
You are specializing your abstract object, but all clients will use the derived class through its base interface.
You are using an abstract base class to factor out duplication within objects in your design, and clients use the concrete implementations through their own interfaces.!
Solution For 1 - Strategy Pattern
If you have the first situation, then you actually have an interface defined by the virtual methods in the abstract class that your derived classes are implementing.
You should consider making this a real interface, changing your abstract class to be concrete, and take an instance of this interface in its constructor. Your derived classes then become implementations of this new interface.
This means you can now test your previously abstract class using a mock instance of the new interface, and each new implementation through the now public interface. Everything is simple and testable.
Solution For 2
If you have the second situation, then your abstract class is working as a helper class.
Take a look at the functionality it contains. See if any of it can be pushed onto the objects that are being manipulated to minimize this duplication. If you still have anything left, look at making it a helper class that your concrete implementation take in their constructor and remove their base class.
This again leads to concrete classes that are simple and easily testable.
As a Rule
Favor complex network of simple objects over a simple network of complex objects.
The key to extensible testable code is small building blocks and independent wiring.
Updated : How to handle mixtures of both?
It is possible to have a base class performing both of these roles... ie: it has a public interface, and has protected helper methods. If this is the case, then you can factor out the helper methods into one class (scenario2) and convert the inheritance tree into a strategy pattern.
If you find you have some methods your base class implements directly and other are virtual, then you can still convert the inheritance tree into a strategy pattern, but I would also take it as a good indicator that the responsibilities are not correctly aligned, and may need refactoring.
Update 2 : Abstract Classes as a stepping stone (2014/06/12)
I had a situation the other day where I used abstract, so I'd like to explore why.
We have a standard format for our configuration files. This particular tool has 3 configuration files all in that format. I wanted a strongly typed class for each setting file so, through dependency injection, a class could ask for the settings it cared about.
I implemented this by having an abstract base class that knows how to parse the settings files formats and derived classes that exposed those same methods, but encapsulated the location of the settings file.
I could have written a "SettingsFileParser" that the 3 classes wrapped, and then delegated through to the base class to expose the data access methods. I chose not to do this yet as it would lead to 3 derived classes with more delegation code in them than anything else.
However... as this code evolves and the consumers of each of these settings classes become clearer. Each settings users will ask for some settings and transform them in some way (as settings are text they may wrap them in objects of convert them to numbers etc.). As this happens I will start to extract this logic into data manipulation methods and push them back onto the strongly typed settings classes. This will lead to a higher level interface for each set of settings, that is eventually no longer aware it's dealing with 'settings'.
At this point the strongly typed settings classes will no longer need the "getter" methods that expose the underlying 'settings' implementation.
At that point I would no longer want their public interface to include the settings accessor methods; so I will change this class to encapsulate a settings parser class instead of derive from it.
The Abstract class is therefore: a way for me to avoid delegation code at the moment, and a marker in the code to remind me to change the design later. I may never get to it, so it may live a good while... only the code can tell.
I find this to be true with any rule... like "no static methods" or "no private methods". They indicate a smell in the code... and that's good. It keeps you looking for the abstraction that you have missed... and lets you carry on providing value to your customer in the mean time.
I imagine rules like this one defining a landscape, where maintainable code lives in the valleys. As you add new behaviour, it's like rain landing on your code. Initially you put it wherever it lands.. then you refactor to allow the forces of good design to push the behaviour around until it all ends up in the valleys.
Write a Mock object and use them just for testing. They usually are very very very minimal (inherit from the abstract class) and not more.Then, in your Unit Test you can call the abstract method you want to test.
You should test abstract class that contain some logic like all other classes you have.
What I do for abstract classes and interfaces is the following: I write a test, that uses the object as it is concrete. But the variable of type X (X is the abstract class) is not set in the test. This test-class is not added to the test-suite, but subclasses of it, that have a setup-method that set the variable to a concrete implementation of X. That way I don't duplicate the test-code. The subclasses of the not used test can add more test-methods if needed.
To make an unit test specifically on the abstract class, you should derive it for testing purpose, test base.method() results and intended behaviour when inheriting.
You test a method by calling it so test an abstract class by implementing it...
If your abstract class contains concrete functionality that has business value, then I will usually test it directly by creating a test double that stubs out the abstract data, or by using a mocking framework to do this for me. Which one I choose depends a lot on whether I need to write test-specific implementations of the abstract methods or not.
The most common scenario in which I need to do this is when I'm using the Template Method pattern, such as when I'm building some sort of extensible framework that will be used by a 3rd party. In this case, the abstract class is what defines the algorithm that I want to test, so it makes more sense to test the abstract base than a specific implementation.
However, I think it's important that these tests should focus on the concrete implementations of real business logic only; you shouldn't unit test implementation details of the abstract class because you'll end up with brittle tests.
one way is to write an abstract test case that corresponds to your abstract class, then write concrete test cases that subclass your abstract test case. do this for each concrete subclass of your original abstract class (i.e. your test case hierarchy mirrors your class hierarchy). see Test an interface in the junit recipies book: http://safari.informit.com/9781932394238/ch02lev1sec6. https://www.manning.com/books/junit-recipes or https://www.amazon.com/JUnit-Recipes-Practical-Methods-Programmer/dp/1932394230 if you don't have a safari account.
also see Testcase Superclass in xUnit patterns: http://xunitpatterns.com/Testcase%20Superclass.html
I would argue against "abstract" tests. I think a test is a concrete idea and doesn't have an abstraction. If you have common elements, put them in helper methods or classes for everyone to use.
As for testing an abstract test class, make sure you ask yourself what it is you're testing. There are several approaches, and you should find out what works in your scenario. Are you trying to test out a new method in your subclass? Then have your tests only interact with that method. Are you testing the methods in your base class? Then probably have a separate fixture only for that class, and test each method individually with as many tests as necessary.
This is the pattern I usually follow when setting up a harness for testing an abstract class:
public abstract class MyBase{
/*...*/
public abstract void VoidMethod(object param1);
public abstract object MethodWithReturn(object param1);
/*,,,*/
}
And the version I use under test:
public class MyBaseHarness : MyBase{
/*...*/
public Action<object> VoidMethodFunction;
public override void VoidMethod(object param1){
VoidMethodFunction(param1);
}
public Func<object, object> MethodWithReturnFunction;
public override object MethodWithReturn(object param1){
return MethodWihtReturnFunction(param1);
}
/*,,,*/
}
If the abstract methods are called when I don't expect it, the tests fail. When arranging the tests, I can easily stub out the abstract methods with lambdas that perform asserts, throw exceptions, return different values, etc.
If the concrete methods invoke any of the abstract methods that strategy won't work, and you'd want to test each child class behavior separately. Otherwise, extending it and stubbing the abstract methods as you've described should be fine, again provided the abstract class concrete methods are decoupled from child classes.
I suppose you could want to test the base functionality of an abstract class... But you'd probably be best off by extending the class without overriding any methods, and make minimum-effort mocking for the abstract methods.
One of the main motivations for using an abstract class is to enable polymorphism within your application -- i.e: you can substitute a different version at runtime. In fact, this is very much the same thing as using an interface except the abstract class provides some common plumbing, often referred to as a Template pattern.
From a unit testing perspective, there are two things to consider:
Interaction of your abstract class with it related classes. Using a mock testing framework is ideal for this scenario as it shows that your abstract class plays well with others.
Functionality of derived classes. If you have custom logic that you've written for your derived classes, you should test those classes in isolation.
edit: RhinoMocks is an awesome mock testing framework that can generate mock objects at runtime by dynamically deriving from your class. This approach can save you countless hours of hand-coding derived classes.
First if abstract class contained some concrete method i think you should do this considered this example
public abstract class A
{
public boolean method 1
{
// concrete method which we have to test.
}
}
class B extends class A
{
#override
public boolean method 1
{
// override same method as above.
}
}
class Test_A
{
private static B b; // reference object of the class B
#Before
public void init()
{
b = new B ();
}
#Test
public void Test_method 1
{
b.method 1; // use some assertion statements.
}
}
If an abstract class is appropriate for your implementation, test (as suggested above) a derived concrete class. Your assumptions are correct.
To avoid future confusion, be aware that this concrete test class is not a mock, but a fake.
In strict terms, a mock is defined by the following characteristics:
A mock is used in place of each and every dependency of the subject class being tested.
A mock is a pseudo-implementation of an interface (you may recall that as a general rule, dependencies should be declared as interfaces; testability is one primary reason for this)
Behaviors of the mock's interface members -- whether methods or properties
-- are supplied at test-time (again, by use of a mocking framework). This way, you avoid coupling of the implementation being tested with the implementation of its dependencies (which should all have their own discrete tests).
Following #patrick-desjardins answer, I implemented abstract and it's implementation class along with #Test as follows:
Abstract class - ABC.java
import java.util.ArrayList;
import java.util.List;
public abstract class ABC {
abstract String sayHello();
public List<String> getList() {
final List<String> defaultList = new ArrayList<>();
defaultList.add("abstract class");
return defaultList;
}
}
As Abstract classes cannot be instantiated, but they can be subclassed, concrete class DEF.java, is as follows:
public class DEF extends ABC {
#Override
public String sayHello() {
return "Hello!";
}
}
#Test class to test both abstract as well as non-abstract method:
import org.junit.Before;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.contains;
import java.util.Collection;
import java.util.List;
import static org.hamcrest.Matchers.equalTo;
import org.junit.Test;
public class DEFTest {
private DEF def;
#Before
public void setup() {
def = new DEF();
}
#Test
public void add(){
String result = def.sayHello();
assertThat(result, is(equalTo("Hello!")));
}
#Test
public void getList(){
List<String> result = def.getList();
assertThat((Collection<String>) result, is(not(empty())));
assertThat(result, contains("abstract class"));
}
}

Categories