@InjectMock是否仅将模拟注入类的全局变量中? [英] Does @InjectMock only inject mocks in global variables of a class?

查看:164
本文介绍了@InjectMock是否仅将模拟注入类的全局变量中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试进行以下测试:

  import org.junit.jupiter.api.BeforeEach;导入org.junit.jupiter.api.extension.ExtendWith;导入org.mockito.InjectMocks;导入org.mockito.Mock;导入org.mockito.MockedStatic;导入org.mockito.junit.jupiter.MockitoExtension;@ExtendWith(MockitoExtension.class)公共类SomeClassTest {//需要模拟和注入@嘲笑私人SomeDao someDao;@InjectMocks私人SomeClass someClass = new someClass();@测试无效test(){when(someDao.retrieveSomeData).thenReturn(10);}} 

这是我要在其中注入对象的简化类,并在方法中使用它:

 公共类SomeClass {私人无效someMethod(){SomeDao someDao = new SomeDao();someDao.retrievSomeData();}} 

但是我也可以使用构造函数中的实例编写如下类:

 公共类SomeClass {SomeDao someDao;公共SomeClass(){someDao =新的SomeDao();}私人无效someMethod(){someDao.retrievSomeData();}} 

结果:它仍然是带有实数对象 someDao.rerieveSomeData()的实数函数,而不是我的模拟对象!为什么?我很困惑.

解决方案

@InjectMock 可以通过三种方式注入模拟:

  1. 构造函数注入:如果您的 SomeClass 具有类型为 SomeDao 的构造函数参数,它将通过模拟作为该参数.
  2. Setter注入:如果 SomeClass 具有参数类型为 SomeDao 的单个setter方法(例如, setDao(SomeDao dao)几个这样的setter,但是一个与模拟程序同名(即 setSomeDao(SomeDao someDao)),它将使用模拟程序作为参数来调用此setter.
  3. 字段注入:如果存在单个类型为 SomeDao 的字段,或者存在多个类型为 SomeDao 的字段,但是一个字段的名称与您的模拟名称相同(即 someDao ),它将使用模拟设置此字段.

对于您的代码,这意味着您永远不应在 SomeClass 类中创建 SomeDao 的实例,而应注入它.在正常的业务代码中,您可以在 SomeClass 之外创建DAO,并将其传递给构造函数(通常是首选的注入变量).然后,在测试中,模仿者会注意执行相同的操作,但要使用模仿代替真正的DAO.

I try to do the following test:

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;


@ExtendWith(MockitoExtension.class)
public class SomeClassTest {
    
    // needs to be mocked and injected
    @Mock
    private SomeDao someDao;

    @InjectMocks
    private SomeClass someClass = new someClass();

    @Test
    void test() {
       when(someDao.retrieveSomeData).thenReturn(10);
    }
}

This the simplified class where the object I want to inject is instantiated and used in a method:

public class SomeClass {
   private void someMethod() {
      SomeDao someDao = new SomeDao();
      someDao.retrievSomeData();
   }
}

But I can also write the class as following with the instantiation in the constructor:

public class SomeClass{
   SomeDao someDao;

   public SomeClass() {
      someDao = new SomeDao();
   }

   private void someMethod() {
      someDao.retrievSomeData();
  }
}

Result: It is still the real function with the reals object someDao.rerieveSomeData() called and not my mocked object! Why? I am rather confused.

解决方案

@InjectMock can inject mocks in three ways:

  1. Constructor injection: If your SomeClass has a constructor parameter of type SomeDao it will pass the mock as that parameter.
  2. Setter injection: If SomeClass has a single setter method with a parameter of type SomeDao (e.g. setDao(SomeDao dao) or there are several such setters, but one has the same name as the mock (i.e. setSomeDao(SomeDao someDao)), it will call this setter with the mock as the parameter.
  3. Field injection: If there is a single field of type SomeDao or there are several fields of type SomeDao, but one field has the same name as your mock (i.e. someDao), it will set this field with the mock.

For your code this means you should never create an instance of SomeDao in your SomeClass class, but instead inject it. In your normal business code you would create the DAO outside of SomeClass and pass it to the constructor (which is usually the prefered injection variant). In your test mockito would then take care to do the same, but with the mock instead of the real DAO.

这篇关于@InjectMock是否仅将模拟注入类的全局变量中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆