【问题标题】:Mockito Error when initializing instance variables from within a contructor从构造函数中初始化实例变量时出现 Mockito 错误
【发布时间】:2016-07-03 12:54:57
【问题描述】:

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

服务等级:

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

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


}

如您所见,我使用 Autowired 的服务类 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时,如何在注入测试对象之前创建mock服务?

【问题讨论】:

    标签: java spring unit-testing mockito


    【解决方案1】:

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

    你可以通过移动这一行来解决这个问题 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();
         }
    }
    

    【讨论】:

      【解决方案2】:

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

      int value = externalService.getValues();
      

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

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

      【讨论】:

        猜你喜欢
        • 2015-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-08
        • 1970-01-01
        • 1970-01-01
        • 2020-09-27
        相关资源
        最近更新 更多