Mockito @InjectMocks 如何工作
Mockito how does @InjectMocks works
从这个Difference between @Mock and @InjectMocks我了解到@InjectMocks被用作注解
创建一个实例并将使用 @Mock 创建的模拟注入其中。
我不认为我理解它是如何工作的。
我有一个示例代码,我想问你 2 个问题,以便直接进入我不清楚的地方。
问题在最后。
我有一个界面:
public interface SimpleAgenda {
public List<String> getAppointments();
public String getAppointment(Date d);
public void addAppointments(Date d, String label);
}
和实现此接口的class:
public class MyAgenda implements SimpleAgenda {
private Map<String, String> appointments;
@Override
public List<String> getAppointments() {
List<String> lst = new ArrayList<String>();
System.out.println(this.appointments == null);
for (String key : this.appointments.keySet()) {
String label = this.appointments.get(key);
lst.add(label);
}
return lst;
}
@Override
public String getAppointment(Date d) {
String dateString = d.toString();
String app = this.appointments.get(dateString);
return app;
}
@Override
public void addAppointments(Date d, String label) {
// TODO Auto-generated method stub
// this behavior is not implemented yet in this class
}
}
终于有考试了 class:
// @RunWith attaches a runner with the test class to initialize the test data
@RunWith(MockitoJUnitRunner.class)
public class AgendaTest {
private static final String LABEL = "This is a mock appointment for: ";
// @InjectMocks annotation is used to create and inject the mock object
@InjectMocks
MyAgenda agenda = new MyAgenda();
// @Mock annotation is used to create the mock object to be injected
@Mock
Map<String, String> mockedAppointments;
@Before
public void createMocks() {
Date d1 = (new GregorianCalendar(120, 4, 15)).getTime();
Date d2 = (new GregorianCalendar(119, 7, 31)).getTime();
String key;
key = d1.toString();
// add the mocked behavior of for a set of given dates
when(mockedAppointments.get(key)).thenReturn(LABEL + key);
key = d2.toString();
// 1. add the mocked behavior of for a set of given dates.
// 2. Strict stubbing that requires that all declared stubs are actually used
// the statement lenient() relax this requirement. Check the manual.
lenient().when(mockedAppointments.get(key)).thenReturn(LABEL + key);
when(mockedAppointments.size()).thenReturn(2);
}
@Test
public void mockTest() {
for (String key : mockedAppointments.keySet()) {
String v = mockedAppointments.get(key);
// Do not worry, we will never reach this line. We are querying the object on
// method that was not mocked (i.e. keySet).
Assert.fail();
}
int size = mockedAppointments.size();
Assert.assertEquals(2, size);
}
@Test
public void simpleTest() {
int appCounter = agenda.getAppointments().size();
// Do not expect that appCounter is 2 (or more in general different than 0) ...
// we are actually querying an object that was not mocked!!!
// See the details of the implementation of the method: MyAgenda.getAppointments()
Assert.assertEquals(0, appCounter);
}
这些是我的问题:
- 在
mockTest()
中,当我调用 mockedAppointments.keySet()
时,它 return 是一个空集...我的问题是:为什么 mockedAppointments.keySet()
不抛出 nullPointerException
(mockedAppointments 仅声明)?也许是因为它是一个模拟?如果是这个原因,为什么模拟不抛出“nullPointerException”?
- 在
simpleTest()
中我们有agenda.getAppointments().size();
; agenda.getAppointments()
包含 System.out.println(this.appointments == null);
并且此行打印“false”是我保留@InjectMocks 注释,否则为“true”,但为什么呢?在第一种情况下(保留@InjectMocks)“agenda”的“appointments”属性在哪里初始化?是不是因为我们把mockedAppointments
的值注入进去才初始化的?如果是,Mockito 是否仅根据测试 class 中定义的 mock 类型和 MyAgenda
中定义的属性类型来执行此操作?
- 问为什么 mockedAppointments.keySet() 不抛出 nullPointerException(仅声明了 mockedAppointments)?也许是因为它是一个模拟?如果是这个原因,为什么模拟不抛出“nullPointerException”?
答案是:因为 mockedAppointments.keySet().size
是 0 而 mockedAppointments.keySet()
是空的,所以这是 mock
的行为
- 2.0 Qn System.out.println(this.appointments == null);行打印“false”是我保留@InjectMocks 注释,否则为“true”,但为什么呢?
答案是:在 junit 或 mockito 中 System.out.println 不起作用,而是使用记录器。
2.1 Qn 第一种情况(保留@InjectMocks)“agenda”的“appointments”属性在哪里初始化?
答案是:它正在模拟 class,例如,对于列表,它初始化为 0 并将值保持为空,除此之外
@InjectMocks
private MyAgenda agenda;
应该这样声明
2.2 Qn是不是因为我们给它注入了mockedAppointments的值,所以初始化了?
答案是:mockedAppointments 和 agenda 没有任何联系,除此之外
相反,你可以使用这个 injectMocks @Mocks
,它有效。
@Mocks
private MyAgenda agenda;
从这个Difference between @Mock and @InjectMocks我了解到@InjectMocks被用作注解 创建一个实例并将使用 @Mock 创建的模拟注入其中。 我不认为我理解它是如何工作的。
我有一个示例代码,我想问你 2 个问题,以便直接进入我不清楚的地方。 问题在最后。
我有一个界面:
public interface SimpleAgenda {
public List<String> getAppointments();
public String getAppointment(Date d);
public void addAppointments(Date d, String label);
}
和实现此接口的class:
public class MyAgenda implements SimpleAgenda {
private Map<String, String> appointments;
@Override
public List<String> getAppointments() {
List<String> lst = new ArrayList<String>();
System.out.println(this.appointments == null);
for (String key : this.appointments.keySet()) {
String label = this.appointments.get(key);
lst.add(label);
}
return lst;
}
@Override
public String getAppointment(Date d) {
String dateString = d.toString();
String app = this.appointments.get(dateString);
return app;
}
@Override
public void addAppointments(Date d, String label) {
// TODO Auto-generated method stub
// this behavior is not implemented yet in this class
}
}
终于有考试了 class:
// @RunWith attaches a runner with the test class to initialize the test data
@RunWith(MockitoJUnitRunner.class)
public class AgendaTest {
private static final String LABEL = "This is a mock appointment for: ";
// @InjectMocks annotation is used to create and inject the mock object
@InjectMocks
MyAgenda agenda = new MyAgenda();
// @Mock annotation is used to create the mock object to be injected
@Mock
Map<String, String> mockedAppointments;
@Before
public void createMocks() {
Date d1 = (new GregorianCalendar(120, 4, 15)).getTime();
Date d2 = (new GregorianCalendar(119, 7, 31)).getTime();
String key;
key = d1.toString();
// add the mocked behavior of for a set of given dates
when(mockedAppointments.get(key)).thenReturn(LABEL + key);
key = d2.toString();
// 1. add the mocked behavior of for a set of given dates.
// 2. Strict stubbing that requires that all declared stubs are actually used
// the statement lenient() relax this requirement. Check the manual.
lenient().when(mockedAppointments.get(key)).thenReturn(LABEL + key);
when(mockedAppointments.size()).thenReturn(2);
}
@Test
public void mockTest() {
for (String key : mockedAppointments.keySet()) {
String v = mockedAppointments.get(key);
// Do not worry, we will never reach this line. We are querying the object on
// method that was not mocked (i.e. keySet).
Assert.fail();
}
int size = mockedAppointments.size();
Assert.assertEquals(2, size);
}
@Test
public void simpleTest() {
int appCounter = agenda.getAppointments().size();
// Do not expect that appCounter is 2 (or more in general different than 0) ...
// we are actually querying an object that was not mocked!!!
// See the details of the implementation of the method: MyAgenda.getAppointments()
Assert.assertEquals(0, appCounter);
}
这些是我的问题:
- 在
mockTest()
中,当我调用mockedAppointments.keySet()
时,它 return 是一个空集...我的问题是:为什么mockedAppointments.keySet()
不抛出nullPointerException
(mockedAppointments 仅声明)?也许是因为它是一个模拟?如果是这个原因,为什么模拟不抛出“nullPointerException”? - 在
simpleTest()
中我们有agenda.getAppointments().size();
;agenda.getAppointments()
包含System.out.println(this.appointments == null);
并且此行打印“false”是我保留@InjectMocks 注释,否则为“true”,但为什么呢?在第一种情况下(保留@InjectMocks)“agenda”的“appointments”属性在哪里初始化?是不是因为我们把mockedAppointments
的值注入进去才初始化的?如果是,Mockito 是否仅根据测试 class 中定义的 mock 类型和MyAgenda
中定义的属性类型来执行此操作?
- 问为什么 mockedAppointments.keySet() 不抛出 nullPointerException(仅声明了 mockedAppointments)?也许是因为它是一个模拟?如果是这个原因,为什么模拟不抛出“nullPointerException”?
答案是:因为mockedAppointments.keySet().size
是 0 而mockedAppointments.keySet()
是空的,所以这是 mock 的行为
- 2.0 Qn System.out.println(this.appointments == null);行打印“false”是我保留@InjectMocks 注释,否则为“true”,但为什么呢?
答案是:在 junit 或 mockito 中 System.out.println 不起作用,而是使用记录器。
2.1 Qn 第一种情况(保留@InjectMocks)“agenda”的“appointments”属性在哪里初始化?
答案是:它正在模拟 class,例如,对于列表,它初始化为 0 并将值保持为空,除此之外
@InjectMocks
private MyAgenda agenda;
应该这样声明
2.2 Qn是不是因为我们给它注入了mockedAppointments的值,所以初始化了?
答案是:mockedAppointments 和 agenda 没有任何联系,除此之外
相反,你可以使用这个 injectMocks @Mocks
,它有效。
@Mocks
private MyAgenda agenda;