@InjectMock 是否只在 class 的全局变量中注入模拟?
Does @InjectMock only inject mocks in global variables of a class?
我尝试做以下测试:
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);
}
}
这是简化的 class,其中实例化了我要注入的对象并在方法中使用:
public class SomeClass {
private void someMethod() {
SomeDao someDao = new SomeDao();
someDao.retrievSomeData();
}
}
但我也可以在构造函数中实例化 class 如下:
public class SomeClass{
SomeDao someDao;
public SomeClass() {
someDao = new SomeDao();
}
private void someMethod() {
someDao.retrievSomeData();
}
}
结果:
它仍然是调用了真实对象 someDao.rerieveSomeData()
的真实函数,而不是我的模拟对象!为什么?我比较迷茫。
@InjectMock
可以通过三种方式注入模拟:
- 构造函数注入:如果您的
SomeClass
具有类型为 SomeDao
的构造函数参数,它将作为该参数传递模拟。
- Setter 注入:如果
SomeClass
有一个带有 SomeDao
类型参数的 setter 方法(例如 setDao(SomeDao dao)
或者有几个这样的 setters,但其中一个与 mock 同名(即 setSomeDao(SomeDao someDao)
),它将以 mock 作为参数调用此 setter。
- 字段注入:如果有一个
SomeDao
类型的字段或有多个 SomeDao
类型的字段,但其中一个字段与您的 mock 同名(即 someDao
), 它将用模拟设置这个字段。
对于您的代码,这意味着您不应该在 SomeClass
class 中创建 SomeDao
的实例,而是注入它。在您的正常业务代码中,您将在 SomeClass
之外创建 DAO 并将其传递给构造函数(这通常是首选的注入变体)。在你的测试中,mockito 会注意做同样的事情,但使用模拟而不是真正的 DAO。
我尝试做以下测试:
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);
}
}
这是简化的 class,其中实例化了我要注入的对象并在方法中使用:
public class SomeClass {
private void someMethod() {
SomeDao someDao = new SomeDao();
someDao.retrievSomeData();
}
}
但我也可以在构造函数中实例化 class 如下:
public class SomeClass{
SomeDao someDao;
public SomeClass() {
someDao = new SomeDao();
}
private void someMethod() {
someDao.retrievSomeData();
}
}
结果:
它仍然是调用了真实对象 someDao.rerieveSomeData()
的真实函数,而不是我的模拟对象!为什么?我比较迷茫。
@InjectMock
可以通过三种方式注入模拟:
- 构造函数注入:如果您的
SomeClass
具有类型为SomeDao
的构造函数参数,它将作为该参数传递模拟。 - Setter 注入:如果
SomeClass
有一个带有SomeDao
类型参数的 setter 方法(例如setDao(SomeDao dao)
或者有几个这样的 setters,但其中一个与 mock 同名(即setSomeDao(SomeDao someDao)
),它将以 mock 作为参数调用此 setter。 - 字段注入:如果有一个
SomeDao
类型的字段或有多个SomeDao
类型的字段,但其中一个字段与您的 mock 同名(即someDao
), 它将用模拟设置这个字段。
对于您的代码,这意味着您不应该在 SomeClass
class 中创建 SomeDao
的实例,而是注入它。在您的正常业务代码中,您将在 SomeClass
之外创建 DAO 并将其传递给构造函数(这通常是首选的注入变体)。在你的测试中,mockito 会注意做同样的事情,但使用模拟而不是真正的 DAO。