PowerMockito verifyNew withArguments 对象和对象数组
PowerMockito verifyNew withArguments of an object and an array of objects
我正在尝试测试一个方法是否创建了一个对象。我几乎可以使用 PowerMockito.verifyNew().withArguments() 但是,传递给构造函数的参数是一个对象和一个对象的 ArrayList。测试的输出是:
实际
invocationSubstitute.performSubstitutionLogic(
1,
6,
11,
13,
[au.edu.sccs.csp3105.NBookingPlanner.Person@2449cff7],
au.edu.sccs.csp3105.NBookingPlanner.Room@62da83ed,
"description"
);
预计
invocationSubstitute.performSubstitutionLogic(
1,
6,
11,
13,
[au.edu.sccs.csp3105.NBookingPlanner.Person@40bffbca],
au.edu.sccs.csp3105.NBookingPlanner.Room@42a9a63e,
"description"
);
我可以看到问题是对象是同一类型但不是同一对象,有没有办法说预期对象的类型正确?
测试:
@RunWith(PowerMockRunner.class)
@PrepareForTest({Planner.class, Meeting.class})
public class MonthInput {
Planner planner;
@Rule
public final TextFromStandardInputStream systemInMock = emptyStandardInputStream();
@Rule
public final ExpectedSystemExit exit = ExpectedSystemExit.none();
@SuppressWarnings("deprecation")
@Before
public void setup() throws Exception {
Meeting meetingMock = Mockito.mock(Meeting.class);
PowerMockito.whenNew(Meeting.class).withAnyArguments().thenReturn(meetingMock);
}
@Test
public void MonthInputofless5() throws Exception {
// make spy
planner = Mockito.spy(Planner.class);
//override main menu with do nothing
Mockito.doNothing().when(planner).mainMenu();
//provide inputs
systemInMock.provideLines("1","6","11","13","ML13.218","Mark Colin","done","description");
//set expected outputs
ArrayList<Person> attendees = new ArrayList<Person>();
attendees.add(new Person("Mark Colin"));
Room where = new Room("ML13.218");
//call the method
planner.scheduleMeeting();
//set passing terms
PowerMockito.verifyNew(Meeting.class).withArguments(1,6,11,13,attendees,where,"description");
}
修复您的代码
对 classes 进行验证的简单修复:在 Person
和 Room
上实施 hashCode
和 equals
,因此 Powermock 验证实际上可以比较两个 objects 代表平等,而不仅仅是依赖 object 参考。
修复你的测试
如果您不想修复您的代码,而是想进行测试,您可以使用 Mockito 匹配器(即 org.mockito.Matchers.eq
或 org.mockito.Matchers.any
)。但请注意,eq
依赖于 equals
,除非您实施它(见上文),否则它不会起作用。但是 any
会匹配该类型的任何 object(惊喜!)
PowerMockito.verifyNew(Meeting.class)
.withArguments(eq(1),eq(6),eq(11),eq(13),
any(List.class),
any(Room.class),
eq("description"));
如果实际值很重要,您可以使用 ArgumentCapture 而不是匹配器并检查捕获的值。
理论上,应该是这样的:
final ArgumentCaptor<Person> personCaptor = forClass(Person.class);
final ArgumentCaptor<Room> roomCaptor = forClass(Room.class);
PowerMockito.verifyNew(Planner.class)
.withArguments(eq(1),eq(6),eq(11),eq(13),
personCaptor.capture(),
roomCaptor.capture(),
eq("description"));
final Person passedParam = personCaptor.getValue();
//do your comparison here
但我没有得到捕获示例 运行,所以也许只有使用普通 Mockito 才有可能。
千万不要!
综上所述,您应该验证您的整体方法。使用 Whitebox-Testing 可能会创建非常脆弱的测试,对重构没有多大帮助,并可能进一步助长糟糕的 class 设计。
Powermockito 的轻率使用是 anti-pattern。这是一个非常强大的工具,用于测试不可测试的东西,即来自互联网黑暗时代的设计糟糕的遗留代码,在那个时代,主页是手工制作的 HTML 和充满摇摆不定的 GIF。
不要将其用于新的未开发项目。只是不要。
而是尝试关注任何操作的可观察结果。调用 scheduleMeeting()
方法可能会产生任何更容易检查的结果——重要的是结果,而不是获取结果的方式。相信我,当构造函数被调用时,没有一个用户会更开心。
结果可能是
- 会议实例(作为 return 值,这在您的示例中最好)
- 规划器中的状态变化(有吸气剂吗?)
- 下游服务/数据库的状态变化
- 一个书面文件
- 写入System.out
的输出
我正在尝试测试一个方法是否创建了一个对象。我几乎可以使用 PowerMockito.verifyNew().withArguments() 但是,传递给构造函数的参数是一个对象和一个对象的 ArrayList。测试的输出是: 实际
invocationSubstitute.performSubstitutionLogic(
1,
6,
11,
13,
[au.edu.sccs.csp3105.NBookingPlanner.Person@2449cff7],
au.edu.sccs.csp3105.NBookingPlanner.Room@62da83ed,
"description"
);
预计
invocationSubstitute.performSubstitutionLogic(
1,
6,
11,
13,
[au.edu.sccs.csp3105.NBookingPlanner.Person@40bffbca],
au.edu.sccs.csp3105.NBookingPlanner.Room@42a9a63e,
"description"
);
我可以看到问题是对象是同一类型但不是同一对象,有没有办法说预期对象的类型正确?
测试:
@RunWith(PowerMockRunner.class)
@PrepareForTest({Planner.class, Meeting.class})
public class MonthInput {
Planner planner;
@Rule
public final TextFromStandardInputStream systemInMock = emptyStandardInputStream();
@Rule
public final ExpectedSystemExit exit = ExpectedSystemExit.none();
@SuppressWarnings("deprecation")
@Before
public void setup() throws Exception {
Meeting meetingMock = Mockito.mock(Meeting.class);
PowerMockito.whenNew(Meeting.class).withAnyArguments().thenReturn(meetingMock);
}
@Test
public void MonthInputofless5() throws Exception {
// make spy
planner = Mockito.spy(Planner.class);
//override main menu with do nothing
Mockito.doNothing().when(planner).mainMenu();
//provide inputs
systemInMock.provideLines("1","6","11","13","ML13.218","Mark Colin","done","description");
//set expected outputs
ArrayList<Person> attendees = new ArrayList<Person>();
attendees.add(new Person("Mark Colin"));
Room where = new Room("ML13.218");
//call the method
planner.scheduleMeeting();
//set passing terms
PowerMockito.verifyNew(Meeting.class).withArguments(1,6,11,13,attendees,where,"description");
}
修复您的代码
对 classes 进行验证的简单修复:在 Person
和 Room
上实施 hashCode
和 equals
,因此 Powermock 验证实际上可以比较两个 objects 代表平等,而不仅仅是依赖 object 参考。
修复你的测试
如果您不想修复您的代码,而是想进行测试,您可以使用 Mockito 匹配器(即 org.mockito.Matchers.eq
或 org.mockito.Matchers.any
)。但请注意,eq
依赖于 equals
,除非您实施它(见上文),否则它不会起作用。但是 any
会匹配该类型的任何 object(惊喜!)
PowerMockito.verifyNew(Meeting.class)
.withArguments(eq(1),eq(6),eq(11),eq(13),
any(List.class),
any(Room.class),
eq("description"));
如果实际值很重要,您可以使用 ArgumentCapture 而不是匹配器并检查捕获的值。
理论上,应该是这样的:
final ArgumentCaptor<Person> personCaptor = forClass(Person.class);
final ArgumentCaptor<Room> roomCaptor = forClass(Room.class);
PowerMockito.verifyNew(Planner.class)
.withArguments(eq(1),eq(6),eq(11),eq(13),
personCaptor.capture(),
roomCaptor.capture(),
eq("description"));
final Person passedParam = personCaptor.getValue();
//do your comparison here
但我没有得到捕获示例 运行,所以也许只有使用普通 Mockito 才有可能。
千万不要!
综上所述,您应该验证您的整体方法。使用 Whitebox-Testing 可能会创建非常脆弱的测试,对重构没有多大帮助,并可能进一步助长糟糕的 class 设计。
Powermockito 的轻率使用是 anti-pattern。这是一个非常强大的工具,用于测试不可测试的东西,即来自互联网黑暗时代的设计糟糕的遗留代码,在那个时代,主页是手工制作的 HTML 和充满摇摆不定的 GIF。 不要将其用于新的未开发项目。只是不要。
而是尝试关注任何操作的可观察结果。调用 scheduleMeeting()
方法可能会产生任何更容易检查的结果——重要的是结果,而不是获取结果的方式。相信我,当构造函数被调用时,没有一个用户会更开心。
结果可能是
- 会议实例(作为 return 值,这在您的示例中最好)
- 规划器中的状态变化(有吸气剂吗?)
- 下游服务/数据库的状态变化
- 一个书面文件
- 写入System.out 的输出