@InjectMock是否仅将模拟注入类的全局变量中? [英] Does @InjectMock only inject mocks in global variables of a class?
问题描述
我尝试进行以下测试:
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
可以通过三种方式注入模拟:
- 构造函数注入:如果您的
SomeClass
具有类型为SomeDao
的构造函数参数,它将通过模拟作为该参数. - Setter注入:如果
SomeClass
具有参数类型为SomeDao
的单个setter方法(例如,setDao(SomeDao dao)
几个这样的setter,但是一个与模拟程序同名(即setSomeDao(SomeDao someDao)
),它将使用模拟程序作为参数来调用此setter. - 字段注入:如果存在单个类型为
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:
- Constructor injection: If your
SomeClass
has a constructor parameter of typeSomeDao
it will pass the mock as that parameter. - Setter injection: If
SomeClass
has a single setter method with a parameter of typeSomeDao
(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. - Field injection: If there is a single field of type
SomeDao
or there are several fields of typeSomeDao
, 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屋!