简体   繁体   English

测试根据输入调用内部方法的公共方法

[英]Test public method that calls internal methods depending on input

So we have this method here that is accessible by the rest of the system which calls underlying methods according to the input. 因此,我们这里有此方法,系统的其余部分可以访问该方法,该方法根据输入调用基础方法。

public SomeReturnObj doSomethingWithInputs(List<Input> inputs) {
  for(Input input : inputs) {
    if(input.getName().equals("A") {
        handleAInput(input);
    }
    else if(input.getName().equals("B") {
        handleBInput(input);
    }
    else { ... }
  }

  // ...
}

To get a good code coverage, I would like to test, that if I put a list with two Inputs with name A and three with name B , the corresponding internal methods are called twice or three times, respectively. 为了获得良好的代码覆盖率,我想测试一下,如果我放置一个包含两个名称为A Inputs和三个名称为B Inputs的列表,则相应的内部方法分别被调用两次或三次。

So I've tried the following: 因此,我尝试了以下方法:

@Test
public void separatingInputsByName() {
    Input entry1 = mock(Input .class);
    Input entry2 = mock(Input .class);
    Input entry3 = mock(Input .class);

    doReturn("A").when(entry1).getName();
    doReturn("A").when(entry2).getName();
    doReturn("B").when(entry3).getName();

    ClassUnderTest sut = mock(ClassUnderTest .class);

    sut.doSomethingWithInputs(Arrays.asList(entry1, entry2, entry3));

    verify(sut).handleAInput(entry1);
    verify(sut).handleAInput(entry2);
    verify(sut).handleBInput(entry3);
}

Unfortunately this does not lead to a proper invocation of the internal methods, probably because the class under test is mocked, so the method implementation is different. 不幸的是,这可能无法正确调用内部方法,这可能是因为被测类是模拟的,因此方法的实现是不同的。

How can I test/verify a method like this properly? 如何正确测试/验证类似方法?

You should use spy() , not mock() . 您应该使用spy() ,而不是mock()

When you use mock() , all methods are "overriden" so that default actions are taken instead of calling the real methods; 当您使用mock() ,所有方法都被“重写”,因此将采取默认操作,而不是调用实际方法。 spy() will simply register method invocations. spy()将仅注册方法调用。

Therefore: 因此:

ClassUnderTest sut = spy(new ClassUnderTest(...));

sut.doSomethingWithInputs(Arrays.asList(entry1, entry2, entry3));

verify(sut).handleAInput(entry1);
verify(sut).handleAInput(entry2);
verify(sut).handleBInput(entry3);
verifyNoMoreInteractions(sut); // if necessary

Also, you can: 另外,您可以:

when(entry1.getName()).thenReturn("A");

Personally, I find it easier to read, but that's a matter of taste, of course. 就我个人而言,我觉得它更容易阅读,但这当然是一个品味问题。

Also, you can use InOrder in your case: 另外,您可以在以下情况下使用InOrder

final InOrder inOrder = inOrder(sut);

inOrder.verify(sut).handleAInput(entry1);
// etc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM