0

Is there any way to mock a method which is injected by spring container using method injection approach.

Let me explain in detail

I have abstract class called Singleton which has abstract method in it

public abstract class Singleton {

    protected abstract LoanField check();

    private LoanField getLoanField(String name) {

    LoanField field = check();

}

and it's corresponding configuration is there in one of the spring-config file.

<bean id="checkDetails" class="com.abc.tools.Singleton">
        <lookup-method name="check" bean="field"/>
    </bean>

    <bean id="field" class="com.abc.tools.LoanField" scope="prototype"/>

Here is my test class in short

Singleton fieldManager = Mockito.mock(Singleton.class, Mockito.CALLS_REAL_METHODS);
LoanField loanField = PowerMockito.mock(LoanField.class);
PowerMockito.when(fieldManager.create()).thenReturn(loanField);

Actual problem here is, in Method Injection Spring overrides a given abstract method of an abstract class and provides an implementation of the overridden method but when i try to stub that method in my test class I'm getting below error

java.lang.AbstractMethodError: com.abc.tools.Singleton.create()Lcom/abc/tools/LoanField;
at com.abc.tools.SingletonTest.loanFiledNotNull(SingletonTest.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:66)
at 

i know its not possible to stub an abstract method but is there any work around to stub the method? Please help me out.

Ps: I mentioned all the depended class in @preparefortest

Praveen Kumar Mekala
  • 628
  • 1
  • 10
  • 26

3 Answers3

0

Make dummy class that extends your abstravct class, add dummy implementation and test this class.

talex
  • 17,973
  • 3
  • 29
  • 66
0

Try with spy,

    Singleton s  = new Singleton(){

    private LoanField getLoanField(String name) {

        LoanField field = check();

    }

    protected LoanField check(){
       return new LoanField();
    }

    }

    Singleton fieldManager = spy(s);
    LoanField loanField = mock(LoanField.class);
    when(fieldManager.create()).thenReturn(loanField);
kuhajeyan
  • 10,727
  • 10
  • 46
  • 71
0

If objects are created via method injection, then best approach is use below code snippet on top of your test code, the moment we run test case @contextconfiguration will create objects for abstract class and you will get hold on abstract methods as well.

@RunWith(MockitoJUnitRunner.class)
@PrepareForTest({LoggerFactory.class,Class.class})
@ContextConfiguration("file:src/test/resources/META-INF/spring-config-test.xml")
public class TestClass {

Basically you should have test xml file which is same as actual xml file and load it using @contextConfiguration.

Thanks.

Praveen Kumar Mekala
  • 628
  • 1
  • 10
  • 26