【问题标题】:unit testing default method calling abstract method in an interface单元测试默认方法调用接口中的抽象方法
【发布时间】:2018-04-04 18:45:09
【问题描述】:

我有一个接口,它有两种方法 - convertList 和 convert。

convertList 有一个默认实现,它为其 inputList 中的每个输入调用 convert

我想为 convertList 编写一个单元测试 -

  • 测试它调用 convert 方法的次数是否与 inputlist 的大小一样多
  • 测试它是否将每个输入的convertedOutput 对象传递到convertedOutputs 列表

下面是我的界面-

public interface MyConverter {
    ConverterOutput convert(final MyDTO input, final String myParam) throws MyDTOConversionException;

    default Collection<ConverterOutput> convertList(
        final Collection<? extends MyDTO> inputList,
        final String myParam)
        throws MyDTOConversionException {
        try {
            List<ConverterOutput> converterOutputs = new ArrayList<>();

            for (MyDTO input : inputList) {
                converterOutputs.add(this.convert(input, myParam));
            }
            return converterOutputs;
        } catch (NullPointerException npe) {
            throw new MyDTOConversionException("Unable to convert dto to converter output", npe);
        }
    }
}

在模拟接口并存根其转换方法时,我无法实现 1。以下是我的测试课。

@SpringBootTest(classes = MyConverter.class)
public class MyConverterTest extends BaseTest {

    class MyDTOImpl extends MyDTO {
        @Override
        public void someAbstractMethod(String param) {
        }
    }

    @Mock
    private ConverterOutput converterOutput;

    @Mock
    private MyConverter myConverter;

    @Mock
    private MyDTOImpl myDTO;

    @Test
    public void testConvertListOfSizeOne() {

        String myParam = "1234";

        Collection<MyDTO> myDTOS = new ArrayList<>();
        myDTOS.add(myDTO);

        try {
            when(myConverter.convert(myDTO, myParam)).thenReturn(converterOutput);
            Collection<ConverterOutput> actualConverterOutputs = myConverter.convertList(myDTOS, myParam);

            // check if times convert method was called is as expected
            verify(myConverter, times(1)).convert(myDTO, myParam);

            // check if number of items in output object are as expected
            Assert.assertEquals(actualConverterOutputs.size(), 1);

            // check if output object is as expected
            for (ConverterOutput c: actualConverterOutputs) {
                Assert.assertSame(c, converterOutput);
            }
        } catch (MyDTOConversionException exception) {
            throw new AssertionError("MyDTOConversionException should not have occurred");
        }
    }
}

以下是我得到的错误

需要但未调用:myConverter.convert(myDTO, "1234"); -> 在 com.abc.project.converters.MyConverterTest.testConvertListOfSizeOne(MyConverterTest.java:49)

但是,还有其他与此模拟的交互: myConverter.convertList( [myDTO], "1234");

【问题讨论】:

    标签: java spring-boot junit interface mockito


    【解决方案1】:

    有两件事帮助我解决了这个问题。

    一,添加一个实现 MyConverter 接口的内部类,因为简单地使用 Mock 注释似乎也覆盖了默认方法,我无法要求 Mockito 调用原始默认方法实现。

    class MyConverterImpl implements MyConverter {
        MyConverterImpl() {}
        @Override
        public ConverterOutput apply(final MyDTO input, final String myParam)
                throws MyDTOConversionException {
            return converterOutput;
        }
    }
    

    接下来,明确要求 Mockito 调用真实方法

    when(myConverter.convertList(myDTOS, myParam)).thenCallRealMethod();
    

    没有这个,convertList 的默认实现就不会被调用。

    【讨论】:

    • @csmckelvey 你是如何获得漂亮的语法高亮显示的?
    • 在问题中添加了 java 标签并将代码缩进了 4 个空格。
    猜你喜欢
    • 2015-11-27
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 2018-06-13
    • 2012-08-27
    • 1970-01-01
    • 2013-07-21
    相关资源
    最近更新 更多