java - 单元测试默认方法调用接口(interface)中的抽象方法

标签 java spring-boot junit interface mockito

我有一个接口(interface),它有两个方法 - ConvertList 和 Convert。

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

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

  • 测试调用convert方法的次数是否与输入列表的大小相同
  • 测试它是否将每个输入的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);
        }
    }
}

在模拟接口(interface)并 stub 其转换方法时,我无法实现 1。以下是我的测试类(class)。

@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");
        }
    }
}

以下是我遇到的错误

Wanted but not invoked: myConverter.convert(myDTO, "1234"); -> at com.abc.project.converters.MyConverterTest.testConvertListOfSizeOne(MyConverterTest.java:49)

However, there were other interactions with this mock: myConverter.convertList( [myDTO], "1234" );

最佳答案

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

一,添加一个实现 MyConverter 接口(interface)的内部类,因为简单地使用 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 的默认实现就不会被调用。

关于java - 单元测试默认方法调用接口(interface)中的抽象方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49658257/

相关文章:

java - Thymeleaf 、 JQuery 和消息属性

spring-boot - Spring boot logback 到文件在 tomcat 上不起作用

java - 单元测试中的模拟域实体

java - 带接口(interface)的 EJB 依赖注入(inject)

java - 为什么三元运算符会因类型不匹配错误而失败?

java - 有人看到我的更新或插入查询有问题吗?我正在使用准备好的声明

java - 您如何在 JUnit 3 中自定义异常处理行为?

java - 将主键分配给 SQL 中的日期类型列

java - Spring Web 应用程序通过本地主机上的 Gmail 发送电子邮件,而不是服务器

junit - 使用TestNG,是否可以动态更改测试名称?