Java 从构造函数中初始化实例变量时出现Mockito错误

Java 从构造函数中初始化实例变量时出现Mockito错误,java,spring,unit-testing,mockito,Java,Spring,Unit Testing,Mockito,我正在使用Mockito为spring应用程序编写单元测试,下面是服务类的单元测试 服务类别: @Service class MyServiceImpl implements MyService{ @Autowired private ExternalService externalService; MyServiceImpl () { int value = externalService.getValues(); } } 正如您所注意到

我正在使用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

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

问题在于在MyServiceImpl类中注入和使用ExternalService依赖关系的方式@Autowired由BeanPostProcessor()处理,该处理器在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();
     }
}

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

int value = externalService.getValues();
为了让Mockito创建一个mock,它必须根据您的帖子调用no-arg构造函数。因此,结果将是
NullPointerException

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