saurabh agarwal
saurabh agarwal

Reputation: 2174

@Autowired dependencies is not getting initialized in base class

I have a test class which is testing an other class method

Other class is structured like this

@Component 
public abstract class ParentOpManager{
     @Autowired 
     private ProcessorRequestWrapper processorRequestWrapper;

     @Autowired 
     private XYProcessor xyProcessor;

}

@Component("childManager")
public class ChildOperationManager extends ParentOpManager{

}

public abstract class ParentClass{
       protected final RequestWrapper requestWrapper;
       protected final ParentOpManager parentOpManager;


       public ParentClass(final RequestWrapper requestWrapper, final ParentOpManager parentOpManager){
           this.requestWrapper = requestWrapper;
           this.parentOpManager = parentOpManager;
       }
}

further I have, child classes extending this class

public class ChildClass extends ParentClass{

      @Autowired 
      private NinjaManager ninjaManager;

      @Autowired
      public ChildClass(final RequestWrapper requestWrapper, @Qualifier("childManager")final ParentOpManager parentOpManager){
          super(requestWrapper, parentOpManager);
      }

      public void methodA() throws Exception {
          Request item = requestWrapper.findItem(); // Problem place 1
      }

      public void methodB() throws Exception {
          Request item = ninjaManager.findItem(); // Problem place 2
      } 
}

I need to test methods of ChildClass. For this I have written a test class.

//@RunWith(MockitoJunitRunner.class)
//@ContextConfiguration
public class TestClass{

    @Mock 
    ChildOperationManager chOpManager;

    @Mock 
    RequestWrapper requestWrapper;

    @InjectMocks
    ChildClass childObject;

    @Before
    public void setup(){
        MockitoAnnotations.initMocks(this);
    }        

    @Test
    public void testSomeMethodA() throws Exception{
        childObject.methodA();
    }
}

So, the problem is when I am class methodA from test class, requestWrapper is NULL. I can not understand why this is happening ?

EDIT:

If i do like

    @Mock 
    ChildOperationManager chOpManager = new ChildOperationManager();

    @Mock 
    RequestWrapper requestWrapper;

    @InjectMocks
    ChildClass childObject = new childObject(requestWrapper, chOpManager);

Problem seams to be resolved. There is some other problem which might be some permission issue. But do you think doing this way is good approach ?

Upvotes: 0

Views: 484

Answers (2)

Vlad Bochenin
Vlad Bochenin

Reputation: 3072

Problem is that Mockito tried to inject mock via constructor in first step.

public class DefaultInjectionEngine {

public void injectMocksOnFields(Set<Field> needingInjection, Set<Object> mocks, Object testClassInstance) {
    MockInjection.onFields(needingInjection, testClassInstance)
            .withMocks(mocks)
            .tryConstructorInjection() <-- Here
            .tryPropertyOrFieldInjection()
            .handleSpyAnnotation()
            .apply();
}

}

And if it found proper constructor, it doesn't try to inject mocks via property or field.

In your case you have constructor for ChildClass, which was picked by Mockito, but you don't initialize a fields in ChildClass.

As workaround, you can resolve it in this way (just don't use mockito injections):

RequestWrapper wrapper;
ChildOperationManager childOperationManager;
ChildClass childObject;

@Before
public void setUp() {
    wrapper = Mockito.mock(RequestWrapper.class);
    childOperationManager = Mockito.mock(ChildOperationManager.class);
    childObject = new ChildClass(wrapper, childOperationManager );
}

Upvotes: 1

alexbt
alexbt

Reputation: 17035

Your error is this:

@Autowired
public ChildClass(final RequestWrapper requestWrapper, @Qualifier("childManager")final ParentOpManager parentOpManager){
    super(requestWrapper, parentOpManager);
}

public void methodA() throws Exception {
    Request item = requestWrapper.findItem(); // this requestWrapper is null 
}

You don't assign the requestWrapper reference in the child. So it remains null.

You should just remove the member variable requestWrapper and parentOpManager from the child. this way, you'll use the parent's one, which is initialized.

Upvotes: 1

Related Questions