首页 > 解决方案 > PowerMockito verifyNew withArguments 对象和对象数组

问题描述

我正在尝试测试一个方法是否创建了一个对象。我几乎可以使用 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");

}

标签: javajunitjunit4powermockito

解决方案


修复你的代码

对您的类进行验证简单修复:实现hashCodeequals打开PersonRoomPowermock 验证实际上可以比较两个对象的相等性,而不仅仅是依赖对象引用。

修复你的测试

如果您不想修复您的代码,而是测试,您可以使用 Mockito 匹配器(即org.mockito.Matchers.eqorg.mockito.Matchers.any)。但是请注意,除非您实施它,否则它eq依赖equals并且不会起作用(见上文)。但any会匹配该类型的任何对象(惊喜!)

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 才有可能。

只是不要!

综上所述,您应该验证您的整体方法。使用白盒测试可能会创建非常脆弱的测试,并且对重构没有多大帮助,并且可能会进一步助长糟糕的类设计。

不谨慎地使用 Powermockito 是一种反模式。它是一个非常强大的工具,用于测试不可测试的,即互联网黑暗时代设计糟糕的遗留代码,主页是手工制作的 HTML 和充满摇摆不定的 GIF。不要将它用于新的、未开发的项目。只是不要。

相反,试着专注于任何行动的可观察结果。调用该scheduleMeeting()方法可能会产生任何更容易检查的结果——重要的是结果,而不是获得它们的方式。相信我,当调用构造函数时,没有一个用户会更开心。

结果可能是

  • 会议的一个实例(作为返回值,在您的示例中最好)
  • 规划器中的状态变化(任何吸气剂?)
  • 下游服务/数据库中的状态变化
  • 书面文件
  • 写入 System.out 的输出

推荐阅读