Search code examples
javajunitabstract-classverificationjmockit

Verifying specific abstract constructor of parent is invoked


In the code base I have the following structure:

abstract class Bar{

    public Bar(){
        ....
    }

    ....        

    public Bar(int x, int y){

    }

    ....
}

Bar is then extended by Foo.

abstract class Foo extends Bar{

    public Foo(){
      super();

        ....
    }

    public Foo(int x){
      super(x,0);  // call parent's specific constructor
      ....
    }

    ....
}

I have tried the following jUnit test case, which cannot compile:

class FooTest{

    Foo _foo;

    @Test
    void testFooConstructor(){
        new Expectations(){
            Bar bar;
            {
                bar = new Bar(anyInt,0); // error, obviously Bar cannot be instantiated.
            }
        }

        _foo = new Foo(anyInt){ // empty implementation
            //Override any abstract methods
        }
    }

}

I have written the above approach because I saw this SO question, but the abstract class may not be initiated, and hence it fails.

Additionally, I have also tried:

class FooTest{

    Foo _foo;

    @Test
    void testFooConstructor(){

        _foo = new Foo(anyInt){ // empty implementation
            //Override any abstract methods
        }

        new Expectations(){
            Bar bar;
            {
                invoke(bar,"Bar",anyInt,0); //Invocations.invoke
            }
        }

        invoke(_foo,"Foo",anyInt);
    }

}

However, my test result is:

java.lang.IllegalArgumentException: No compatible method found: Bar(int,int) at unit.src.com.test.FooTest$1.(line number)

How can I achieve the desired result? Is there a way to implement this test?


Solution

  • This is an unusual testing scenario, but it can be done using JMockit with a @Mock method for the constructor in the abstract base class:

    public class FooTest
    {
        @Test
        void verifyCallToSuperConstructor()
        {
            new MockUp<Bar>() {
                @Mock(invocations = 1) // verifies one call will occur
                void $init(int x, int y)
                {
                    assertEquals(0, y);
                }
            };
    
            new Foo(123);
        }
    }