I have an interesting JUnit problem here (JUnit 4.12). I have a base class that only has static methods. They have to be static, because of the way they're used. I inherit other classes from the base class. So, if the base class is Base, we have ChildA and ChildB.
Most of the methods are contained in the base class, but it has to know which child it actually is (just calling the methods as the base class is invalid). This is done via a static data member in the base class:
public class Base {
protected static ChildType myType = ChildType.Invalid;
...
}
Each child sets the data member via a static initializer, thus:
static {
myType = ChildType.ChildA;
}
Then when the methods are called, the base class knows what type it is and loads the appropriate configurations (the type is actually a configuration name).
This all works perfectly when running the application. Stepping through it in the debugger and through log messages, I can see the appropriate types are set and the methods load the appropriate configurations based on the child type.
The problem arises when using JUnit. We have some JUnit tests to test each of the base class methods. Since calling the methods on just the base class is invalid, we call the methods on the child classes, thus:
bool result = ChildA.methodTwo();
This ''always fails''. Why? The static initializer never gets called. When running the code as an application, it gets called, and everyone is happy. When I run it as a JUnit test, the static initializer is skipped and the methods have invalid data. What is JUnit doing that skips the static initializer? Is there a way around it?
Details
In reality, we're not calling the method as I posted above. I just wanted the example to be as clear as possible. In reality, we have a Web Service written with the Jersey framework. The method called is one of the REST endpoints.
#POST
#Produces(MediaType.TEXT_PLAIN)
public String methodPost() {
...
return new String( itWorked ? "success" : "fail" );
}
And we call it like this (sorry about the ugly syntax, it's just the way it works):
#Test
public void testThePost() throws Exception {
javax.ws.rs.core.Response response = target("restapi/").request().post(Entity.entity(null, MediaType.TEXT_PLAIN));
assertEquals( 200, response.getStatus() );
}
All the GET tests work, and the static initializer is called on all of them. It's just this POST that fails, and only when running the JUnit test.
You are trying to implement polymorphic behavior for static methods, a language feature that is present in other programming languages, but is missing in Java.
[myType is] a protected member of the base class
Relying on static initializers to set static fields in the base class is very fragile, because multiple subclasses "compete" for a single field in the base class. This "locks in" the behavior of the base class into the behavior desirable for the subclass whose initializer ran last. Among other bad things, it denies a possibility of using multiple subclasses along with the Base class, and makes it possible for ChildA.methodTwo() to run functionality designed for ChildB.methodTwo(). In fact, there is no ChildA.methodTwo() and ChildB.methodTwo(), there's only Base.methodTwo() that relies on information prepared for it by the static initialization sequence.
There are several solutions to this problem. One possibility is to pass Class<Child###> object to methods of the base class:
class Base {
public static void method1(Class childConfig, String arg) {
...
}
public static void method2(Class childConfig, int arg1, String arg2) {
...
}
}
Now the callers would need to change
ChildA.method1("hello");
ChildA.method2(42, "world");
to
Base.method1(ChildA.class, "hello");
Base.method2(ChildA.class, 42, "world");
Another solution would be to replace static implementation with non-static, and use "regular" polymorphic behavior in conjunction with singletons created in derived classes:
class Base {
protected Base(Class childConfig) {
...
}
public void method1(String arg) {
...
}
public void method2(int arg1, String arg2) {
...
}
}
class ChildA extends Base {
private static final Base inst = new ChildA();
private ChildA() {
super(ChildA.class);
}
public static Base getInstance() {
return inst;
}
... // Override methods as needed
}
class ChildB extends Base {
private static final Base inst = new ChildB();
private ChildB() {
super(ChildB.class);
}
public static Base getInstance() {
return inst;
}
... // Override methods as needed
}
and call
ChildA.getInstance().method1("hello");
ChildA.getInstance().method2(42, "world");
There is only one Base.myType field shared amongst all accessors: Base, ChildA and ChildB. The following sequence of events could cause the failures you are seeing:
JUnit test invoking ChildA.methodOne() starts execution, causing the JVM classloader to load ChildA.class and execute its static initializer block, setting Base.myType to ChildType.ChildA,
JUnit test invoking ChildB.methodOne() starts execution, causing the JVM classloader to load ClassB.class and execute its static initializer block, setting Base.myType to ChildType.ChildB, then
JUnit test invoking ChildA.methodTwo() starts execution, not executing the ChildA static initializer block first as ChildA has already been loaded by the JVM classloader, resulting in the JUnit test failing because Base.myType (and thus ChildA.myType) presently equals ChildType.ChildB.
The basic design issue is that part of your code expects the child types to own the myType field but that field is in fact shared by all child types.
Please provide the order in which your JUnit tests are being run to verify the above theory. Thanks!
addendum: Thanks for clarifying in comments that you only have one JUnit test invoking just ChildA.methodTwo() which is only defined in Base, not ChildA. What is happening is likely the JVM deciding that ChildA need not be initialized just to call its parent Base class's methodTwo() method. #ShyJ provides a very nice explanation of this for parent and child static field access at https://stackoverflow.com/a/13475305/1840078. I believe that something similar is happening in your JUnit test.
addendum 2: Below is my code modeling and reproducing the described issue of myType having the value ChildType.Invalid during the JUnit test to the best of current understanding:
public enum ChildType {
Invalid, ChildA
}
public class Base {
protected static ChildType myType = ChildType.Invalid;
public static boolean methodTwo() {
return true;
}
}
public class ChildA extends Base {
static {
myType = ChildType.ChildA;
}
}
public class ChildATest {
#org.junit.Test
public void test() {
boolean result = ChildA.methodTwo();
System.out.println("result: " + result);
System.out.println("Base.myType: " + Base.myType);
}
}
Output of execution of ChildATest.test():
result: true
Base.myType: Invalid
I decided to try what #Arkdiy suggested and have pass-through methods in the child classes.
Let me reiterate: the code, as I had it, works perfectly when run as an application. Only when running via JUnit does it fail.
So now I have something similar to the below:
public class BaseClass {
protected static ChildType myType = ChildType.Invalid;
...
public static boolean methodTwoBase() {
...
}
}
public class ChildA extends BaseClass {
public static boolean methodOne() {
...
}
public static boolean methodTwo() {
myType = ChildType.ChildA;
return methodTwoBase();
}
}
public class ChildB extends BaseClass {
public static boolean methodOne() {
...
}
public static boolean methodTwo() {
myType = ChildType.ChildB;
return methodTwoBase();
}
}
Since I can't override static methods, the version of the method in the base class has a different signature (methodTwoBase() instead of methodTwo). I tried it as a regular application and in JUnit and it works both ways.
Kind of an interesting problem, and I blame JUnit. Thanks for all the input!
Related
When designing a fluid API, sometimes I want to use Interface return types so that the caller can easily follow the available methods or gets compiler errors if he does not (the Step Builder pattern is an example).
But when I want to use interfaces just to point to the next available method, like:
package packageone;
public class SomeClass implements CanPrint {
private SomeClass() {
}
public static CanPrint get() {
return new SomeClass();
}
#Override
public void print() {
System.out.println("Runs fine!");
}
}
public interface CanPrint {//Compile error: must be defined in own file
public void print();
}
However, firing up a quick test works fine (the following code prints "Runs fine!"):
package packagetwo;
import packageone.CanPrint;
import packageone.SomeClass;
public class Main {
public static void main(String[] args) {
CanPrint returnType = SomeClass.get();
returnType.print();
}
}
The compiler can be 'fooled' by wrapping the entire class:
package packageone;
public class Wrapper {
public static CanPrint get() {
return SomeClass.get();
}
public static class SomeClass implements CanPrint {
public static CanPrint get() {
return new SomeClass();
}
private SomeClass() {
}
#Override
public void print() {
System.out.println("Runs fine!");
}
}
public interface CanPrint {
public void print();
}
}
So currently when I want to keep the interfaces in the same place as the only code that is intended to use it (as the caller only needs the method), I wrap it in a wrapper class which only points to the same method in the inner class.
Why is this restriction in place? The other class can import the interface, use it, even implement their own version if they desire to do so. All of this seems to run without problems. Yet it does not compile.
Note: I've simplified my examples as much as I could, but because of this it might be less clear why one would choose this design.
Why is this restriction in place?
It makes it easier for the compiler and humans to find the source file containing a top-level class.
You can expose the interface by:
Placing the interface in a separate file, like ISomeClassCanPrint.
Or nesting the interface in the class that returns an instance. Your wrapper is close to this approach.
Here's another example of a nested interface:
public static class SomeClassFactory {
public interface CanPrint {
public void print();
}
public static CanPrint get() {
return new SomeClass();
}
public static class SomeClass implements CanPrint {
#Override
public void print() {
System.out.println("Runs fine!");
}
}
}
More detail
The restriction is covered by the Java Language Specification, section 7.6: Top level type declarations:
If and only if packages are stored in a file system (ยง7.2), the host system may choose to enforce the restriction that it is a compile-time error if a type is not found in a file under a name composed of the type name plus an extension (such as .java or .jav) if either of the following is true:
The type is referred to by code in other compilation units of the package in which the type is declared.
The type is declared public (and therefore is potentially accessible from code in other packages).
This restriction implies that there must be at most one such type per compilation unit. This restriction makes it easy for a Java compiler to find a named class within a package. In practice, many programmers choose to put each class or interface type in its own compilation unit, whether or not it is public or is referred to by code in other compilation units.
So while you are allowed to declare multiple top-level classes in a single file, at most one can be exposed for access outside the file.
You can, however, expose as many nested classes as you want.
This is a bit of a tricky one to explain, but let's say I have two classes A and B. A contains a static list of factory objects that are registered by each object that provides such a factor. In this example B is such a class and provides an imaginary Factory implementation.
Class A:
public class A {
protected static Map<String, Factory> registered = new HashMap<String, Factory>();
protected static register(String name, Factory factory) {
registered.put(name, factory);
}
public A() {
// Do something with the factories we've registered
}
}
Class B:
public class B {
static {
A.register("Foo", new Factory() {
public Object create() {
return new B();
}
});
}
public B() {
// Create a new instance of class B
}
}
In my program for some strange reason the static block within B is never called, so when I start interacting with A no factories have been registered so it can't do what it needs to do.
If I move the creation of each Factory into A directly there is no problem of course. I'm working under the assumption that because there are no clear references to B from any class that the compiler isn't recognising there's a link between A and B so doesn't bother with B at all. Is there anything I can do to work around this? I'd hoped to avoid adding each new factory into A directly as it makes maintenance more difficult than having new factories simply register themselves, but clearly having none of them work at all is even worse; still, I'd like to somehow get it to work as intended if I can.
In case it's relevant, the particular JVM I'm working with is the Android JVM, could this be a side-effect of some optimisation that that that JVM is using?
You can read about class loading in this blog post. The point is that a class won't be loaded until it is referenced. And the static blocks of a class won't be executed until the class is loaded. The rules are
an Instance of class is created using either new() keyword or using reflection using class.forName(), which may throw ClassNotFoundException in Java.
an static method of Class is invoked.
an static field of Class is assigned.
an static field of class is used which is not a constant variable.
if Class is a top level class and an assert statement lexically nested within class is executed.
A solution is to either instantiate B or call a no-op static method (or any of the above).
public class B {
static {
A.register("Foo", new Factory() {
public Object create() {
return new B();
}
});
}
public void static noOp() {}
public B() {
// Create a new instance of class B
}
}
...
B.noOp();
The Oracle JVM spec states this here.
I have the following problem in Java:
I have a base class and a derived class and I have a method in the base class. When I call the Base's foo method through Derived I want to get the Derived's class. The foo method can be generic if it can be done that way.
class Base
{
static void foo()
{
// I want to get Derived class here
// Derived.class
}
}
class Derived extends Base
{
}
Derived.foo();
Thanks for your help!
David
That's not the way that static methods work. You'll have to implement Derived.foo(), do whatever it is that's special to Derived, and that method then calls Base.foo(). If you really need the type information, you could create Base.foo0(Class klass).
But to be honest, any static method that needs to know that type of the class that it's invoked on should probably be an instance method.
Well, the caller of Derived.foo() knows what they are calling, so you could alter your methods thus:
class Base
{
static void foo(Class< T > calledBy)
{
// I want to get Derived class here
// Derived.class
}
}
class Derived extends Base
{
}
Derived.foo(Derived.class);
static methods are not inheritated. Static methods with the same signature can only hide similar methods in the superclass. This means that you never will see the result you probably want - you always exactly know the enclosing class. It is never possible that the static method is somehow "within" another class. So it is just impossible to produce the desired result. Calling a static method from a subclass or an instance is a bad idea for this reason as it just hides the real class. (IDEs and static code analysis tools can mark or correct this.)
Sources:
JLS http://java.sun.com/docs/books/jls/second_edition/html/classes.doc.html#227961
http://docs.oracle.com/javase/tutorial/java/IandI/override.html
So what works with inherited methods does not work with static methods that are not inherited.
class Base {
static void foo() {
// Only the static context is available here so you can't get class dynamic class information
}
void bar() {
System.out.println(getClass());
}
}
class Derived extends Base {
}
class Another extends Base {
static void foo() {
// No super call possible!
// This method hides the static method in the super class, it does not override it.
}
void bar() {
super.bar();
}
}
Derived derived = new Derived();
derived.bar(); // "class Derived"
Base base = new Base();
base.bar(); // "class Base"
// These are only "shortcuts" for Base.foo() that all work...
derived.foo(); // non-static context
Derived.foo(); // could be hidden by a method with same signature in Derived
base.foo(); // non-static context
Base.foo(); // Correct way to call the method
Another a = new Another();
a.foo(); // non-static context
Another.foo();
Is it good idea that the language allows this? - Hm. I think it is telling that IDEs and code analysis tools warn and can even correct this automatically.
Not possible, Derived.foo() will simply give code for Base.foo().
Derived.foo();
This will go to foo defined in Derived, if one is defined there:
class Base {
static void foo() {
System.out.println("Base");
}
}
class Der extends Base {
static void foo() {
System.out.println("Der");
}
}
class Check {
public static void main(String[] args) {
Base.foo();
Der.foo();
}
}
When I run it:
javac -g Check.java && java Check
Base
Der
So what is your question? If you to require that each derived class implement foo that is not possible to enforce in Java.
I am new to Java testing with JUnit. I have to work with Java and I would like to use unit tests.
My problem is: I have an abstract class with some abstract methods. But there are some methods which are not abstract. How can I test this class with JUnit? Example code (very simple):
abstract class Car {
public Car(int speed, int fuel) {
this.speed = speed;
this.fuel = fuel;
}
private int speed;
private int fuel;
abstract void drive();
public int getSpeed() {
return this.speed;
}
public int getFuel() {
return this.fuel;
}
}
I want to test getSpeed() and getFuel() functions.
Similar question to this problem is here, but it is not using JUnit.
In JUnit FAQ section, I found this link, but I don't understand what the author want to say with this example. What does this line of code mean?
public abstract Source getSource() ;
If you have no concrete implementations of the class and the methods aren't static whats the point of testing them? If you have a concrete class then you'll be testing those methods as part of the concrete class's public API.
I know what you are thinking "I don't want to test these methods over and over thats the reason I created the abstract class", but my counter argument to that is that the point of unit tests is to allow developers to make changes, run the tests, and analyze the results. Part of those changes could include overriding your abstract class's methods, both protected and public, which could result in fundamental behavioral changes. Depending on the nature of those changes it could affect how your application runs in unexpected, possibly negative ways. If you have a good unit testing suite problems arising from these types changes should be apparent at development time.
Create a concrete class that inherits the abstract class and then test the functions the concrete class inherits from the abstract class.
With the example class you posted it doesn't seem to make much sense to test getFuel() and getSpeed() since they can only return 0 (there are no setters).
However, assuming that this was just a simplified example for illustrative purposes, and that you have legitimate reasons to test methods in the abstract base class (others have already pointed out the implications), you could setup your test code so that it creates an anonymous subclass of the base class that just provides dummy (no-op) implementations for the abstract methods.
For example, in your TestCase you could do this:
c = new Car() {
void drive() { };
};
Then test the rest of the methods, e.g.:
public class CarTest extends TestCase
{
private Car c;
public void setUp()
{
c = new Car() {
void drive() { };
};
}
public void testGetFuel()
{
assertEquals(c.getFuel(), 0);
}
[...]
}
(This example is based on JUnit3 syntax. For JUnit4, the code would be slightly different, but the idea is the same.)
If you need a solution anyway (e.g. because you have too many implementations of the abstract class and the testing would always repeat the same procedures) then you could create an abstract test class with an abstract factory method which will be excuted by the implementation of that test class. This examples works or me with TestNG:
The abstract test class of Car:
abstract class CarTest {
// the factory method
abstract Car createCar(int speed, int fuel);
// all test methods need to make use of the factory method to create the instance of a car
#Test
public void testGetSpeed() {
Car car = createCar(33, 44);
assertEquals(car.getSpeed(), 33);
...
Implementation of Car
class ElectricCar extends Car {
private final int batteryCapacity;
public ElectricCar(int speed, int fuel, int batteryCapacity) {
super(speed, fuel);
this.batteryCapacity = batteryCapacity;
}
...
Unit test class ElectricCarTest of the Class ElectricCar:
class ElectricCarTest extends CarTest {
// implementation of the abstract factory method
Car createCar(int speed, int fuel) {
return new ElectricCar(speed, fuel, 0);
}
// here you cann add specific test methods
...
I would create a jUnit inner class that inherits from the abstract class. This can be instantiated and have access to all the methods defined in the abstract class.
public class AbstractClassTest {
public void testMethod() {
...
}
}
class ConcreteClass extends AbstractClass {
}
You could do something like this
public abstract MyAbstractClass {
#Autowire
private MyMock myMock;
protected String sayHello() {
return myMock.getHello() + ", " + getName();
}
public abstract String getName();
}
// this is your JUnit test
public class MyAbstractClassTest extends MyAbstractClass {
#Mock
private MyMock myMock;
#InjectMocks
private MyAbstractClass thiz = this;
private String myName = null;
#Override
public String getName() {
return myName;
}
#Test
public void testSayHello() {
myName = "Johnny"
when(myMock.getHello()).thenReturn("Hello");
String result = sayHello();
assertEquals("Hello, Johnny", result);
}
}
You can instantiate an anonymous class and then test that class.
public class ClassUnderTest_Test {
private ClassUnderTest classUnderTest;
private MyDependencyService myDependencyService;
#Before
public void setUp() throws Exception {
this.myDependencyService = new MyDependencyService();
this.classUnderTest = getInstance();
}
private ClassUnderTest getInstance() {
return new ClassUnderTest() {
private ClassUnderTest init(
MyDependencyService myDependencyService
) {
this.myDependencyService = myDependencyService;
return this;
}
#Override
protected void myMethodToTest() {
return super.myMethodToTest();
}
}.init(myDependencyService);
}
}
Keep in mind that the visibility must be protected for the property myDependencyService of the abstract class ClassUnderTest.
You can also combine this approach neatly with Mockito. See here.
My way of testing this is quite simple, within each abstractUnitTest.java. I simply create a class in the abstractUnitTest.java that extend the abstract class. And test it that way.
You can not test whole abstract class. In this case you have abstract methods, this mean that they should be implemented by class that extend given abstract class.
In that class programmer have to write the source code that is dedicated for logic of his.
In other words there is no sens of testing abstract class because you are not able to check the final behavior of it.
If you have major functionality not related to abstract methods in some abstract class, just create another class where the abstract method will throw some exception.
As an option, you can create abstract test class covering logic inside abstract class and extend it for each subclass test. So that in this way you can ensure this logic will be tested for each child separately.
You don't need a fancy Mockito add on, or anonymous classes, or whatever other things the other answers are recommending. Junit supports test classes extending each other: so, write a thorough, abstract test class (literally just make the test class abstract) for your abstract base class, that examines how each of the methods behave. Do these tests on a set of instance-variable objects, that are set up as you desire in an #BeforeEach method in this base test class. Have that method call an abstract allocateObjects() method, which will do all the object allocation.
Then, for each class that extends your abstract base, have a test class that extends the abstract test class you just wrote. This test class will do the actual object allocation in the overridden allocateObjects() method. The objects it allocates will be used by the methods in the parent test class: methods which are inhertied by this test class, and therefore run as a part of its testing.
Could you do factory tomfoollery? I guess: but since you probably need to create test classes for each subclass anyways, you might as well just keep things simple with inheritence. I suppose if you have a lot of subclasses, and none of them do anything that is worth testing appart from the superclass stuff, it would be worth it: but why on earth would you be creating subclasses in that case?
Instead of doing #inject mock on abstract class create a spy and create a anonymous implementation in the test class itself and use that to test your abstract class.Better not to do that as there should not be any public method on with you can do unit test.Keep it protected and call those method from implemented classes and test only those classes.
Given the following three classes how can I use reflection to call the initialize function for the parent class(es) and then the subclass:
public class Test {
public static void main(String[] args) {
ExtendedElement ee = new ExtendedElement();
initialize(ee);
}
public static void initialize(Element element) {
System.out.println(element.getClass());
initialize(element.getClass());
}
public static void initialize(Class clazz) {
System.out.println(clazz.getClass());
}
}
public class Element {
protected String value;
public String getValue() { return value; }
public void setValue(String value) { this.value = value; }
}
public class ExtendedElement extends Element {
protected String extendedValue;
public void setExtendedValue(String extendedValue) {
this.extendedValue = extendedValue;
}
public String getExtendedValue() { return extendedValue; }
}
I'm not quite sure on how to paramertize the initialize function in the Test class, as the clazz parameter is a raw type.
What I essentially need is to call initialize up the class hierarchy if what I pass into initialize is of a subclass of Element.
Something like the following:
public void initialize(Class clazz) {
if (Element.class.isInstance(clazz.getClass().getSuperclass()) {
initialize(clazz.getClass().getSuperclass());
}
//Work to call initialize function
}
Edit 1:
Can't I parameterize the above pseudo function differently to retain the type of the object and then call the function I need to?
What I'm trying to do is avoid having to have the same method overridden for each of my classes and allow some inheritance for my Selenium 2 Page Objects. What I need to do is be able to is introspect the superclass(es) of my self and initialize each of my WebElement fields prior to running tests on these fields.
These are being injected with spring, and to further complicate things I am allowing tests to be written using Spring Expression language. I am lazy loading my beans, and using the InitializingBean interface to attempt to initialize my WebElements prior to their usage to avoid NPEs.
I had to wrap the WebElements with a custom object so that I could inject the location strategies using spring (We reuse a lot of pieces, but they have different ids / class names dependent upon where they are used in the application; this was done prior to me getting here and will not be changed at this time despite my arguments for consistency). For example we have a date widget that has different granularities, sometimes we need just a month, sometimes month and year, etc... It'd be nice if I could use an abstract class and break these commonalities down to their least common denominator and extend from there. To do that I need to be able to do the following in my base class:
public abstract class PageObject implements InitializingBean {
...
public void afterPropertiesSet() {
//Pass in concrete impl we are working with - this allows me to initialize properly
initializeWebElements(this.getClass());
}
...
public void initializeWebElements(Class clazz) {
//This does not grab inherited fields, which also need to be initialized
for (Field field : clazz.getDeclaredFields()) {
if (WidgetElement.class == field.getType()) {
Method getWidgetElement = clazz.getDeclaredMethod("get" +
StringUtils.capitalize(field.getName()), new Class [] {});
WidgetElement element =
(WidgetElement) getWidgetElement.invoke(this, new Object [] {});
element.initElement();
}
}
You can't call a method at a specific level. The only thing is you have access to the super keyword inside the class itself.
To make this work, you want to call super.initialize() from within each subclass, then just call it via reflection.
This is not C++, where you can call a specific method at a specific level of the inheritance hierarchy.
I'm not quite sure on how to parameterize the initialize function in the Test class, as the clazz parameter is a raw type.
Nothing in your example requires you to make use of the generic type parameter, so declare it as Class<?>.
I don't understand what your initialize methods are really trying to do, but there are a number of problems:
You seem to have one initialize method that takes an instance (of Element) as an argument, and another that takes a Class object as an argument. That's really apples and oranges stuff ... and you need to explain what you are trying to do.
Your attempt at fleshing out the method contains this:
Element.class.isInstance(clazz.getClass().getSuperclass())
This will never evaluate to true, because it is asking if some Class object is an instance of the Element class. (What is more, clazz.getClass().getSuperclass() is actually going to be the same as java.lang.Object.class. The class of a Class object is java.lang.Class and its superclass is java.lang.Object).
But I can't figure out what it should be, because you don't clearly describe what you are trying to achieve.
Here is my temporary solution, leaving question open to hopefully gather some better answers though for my use case.
public abstract class PageObject implements InitializingBean {
...
public void afterPropertiesSet() {
Class clazz = this.getClass();
do {
initializeElements(clazz);
clazz = clazz.getSuperclass();
} while (clazz != null);
}