Mockito在构造函数中初始化实例变量时出错

时间:2016-03-17 09:15:10

标签: java spring unit-testing mockito

我正在使用Mockito编写spring应用程序的单元测试,以下是服务类的单元测试。

服务类:

@Service
class MyServiceImpl implements MyService{
    @Autowired
    private ExternalService externalService;

    MyServiceImpl () {
        int value = externalService.getValues();
    }


}

正如您所注意到的,我使用来自名为ExternalService的服务类(自动装配)中的方法在构造函数内初始化实例变量。

测试类:

public class LotteryServiceImplTest {
    @InjectMocks
    private MyServiceImpl myService;

    @Mock
    private ExternalService externalService;

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

    @Test
    public void testGetLotteryResult() {
        //test specific code
    }
}

当我运行测试时,它会出错:

org.mockito.exceptions.base.MockitoException: 
    Cannot instantiate @InjectMocks field named 'value' of type 'MyServiceImpl'.
    You haven't provided the instance at field declaration so I tried to construct the instance.
    However the constructor or the initialization block threw an exception : null

当测试对象的构造函数依赖于mock时,如何在注入测试对象之前创建模拟服务?

2 个答案:

答案 0 :(得分:2)

问题在于您在MyServiceImpl类中注入和使用ExternalService依赖项的方式。 @Autowired由BeanPostProcessor()处理,该Bean在实例化bean之后运行。因此,只有在构造函数运行后才初始化externalService引用的值。所以你不能在你的构造函数中使用它,因为那时它仍然是null;

您可以通过移动此行来修复此问题:int value = externalService.getValues();从构造函数到您的业务方法。

如果要在启动时初始化一次值,可以使用@PostConstruct初始化回调,如此

@Service
class MyServiceImpl implements MyService{
    @Autowired
    private ExternalService externalService;
    private int value;

    MyServiceImpl () {

    }

    @PostConstruct
     public void initValue(){
        value = externalService.getValues();
     }
}

答案 1 :(得分:1)

您正在尝试实例化MyServiceImpl类,并且externalService构造函数中的以下行中的自动装配MyServiceImpl变量绝对为空

int value = externalService.getValues();

为了让Mockito创建一个模拟,它必须根据你的帖子调用没有arg构造函数。结果将是NullPointerException

进行此初始化的最佳位置之一是@Before带注释的方法,您可以在其中调用externalService.getValues()并使用setter方法设置value实例变量。