我正在使用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时,如何在注入测试对象之前创建模拟服务?
答案 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
实例变量。