@Autowired依赖项未在基类中初始化

时间:2017-01-12 10:50:53

标签: java spring mockito

我有一个测试其他类方法的测试类

其他类的结构如下

@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;
       }
}

我还有,扩展这个类的子类

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
      } 
}

我需要测试ChildClass的方法。为此我写了一个测试类。

//@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();
    }
}

所以,问题是当我从测试类开始类methodA时,requestWrapper是NULL。我不明白为什么会这样?

编辑:

如果我喜欢

    @Mock 
    ChildOperationManager chOpManager = new ChildOperationManager();

    @Mock 
    RequestWrapper requestWrapper;

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

问题接缝有待解决。还有一些其他问题可能是一些许可问题。但你认为这样做是好方法吗?

2 个答案:

答案 0 :(得分:1)

您的错误是:

@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 
}

您没有在子项中分配requestWrapper引用。所以它仍然是空的。

您应该从子项中删除成员变量requestWrapperparentOpManager。通过这种方式,您将使用已初始化的父对象。

答案 1 :(得分:1)

问题是Mockito试图在第一步中通过构造函数注入mock。

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();
}

}

如果它找到了正确的构造函数,它不会尝试通过属性或字段注入模拟。

在你的情况下,你有ChildClass的构造函数,它是由Mockito选择的,但是你没有初始化ChildClass中的字段。

作为解决方法,您可以通过这种方式解决它(只是不要使用mockito注入):

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 );
}