有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

mockito junit未涵盖接口中的java方法

我正在使用mockito junit测试我的一段代码。随着工作的进行,我发现我正在测试的主文件中实现了一个接口,当测试运行时,我发现接口方法被称为get的那一行被覆盖了,但真正的方法没有被覆盖

这是主文件的代码:

public class ExtractCurrencyDataTask {

private static final Logger LOGGER = LoggerFactory.getLogger(ExtractCurrencyDataTask.class);

@Autowired
private ExtractCurrencyService extractCurrencyService;

public void writeCurrencyListToFile(List<Currency> currencyList) {
    if (currencyList != null && !currencyList.isEmpty()) {
        String dir = "A path";
        String fileName = "A filename";
        String writeToFile = dir + "/" + fileName + ".writing";
        String renameFile = dir + "/" + fileName + ".dat";

        BufferedWriter writer = null;
        FileWriter fileWriter = null;
        try {
            fileWriter = new FileWriter(writeToFile);
            writer = new BufferedWriter(fileWriter);
            extractCurrencyService.extractCurrencyList(currencyList, writer);
        } catch (Exception e) {
            throw new RuntimeException("Error writing Currency codes", e);
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                    fileWriter.close();
                } catch (IOException e) {
                    LOGGER.info("Exception occured while closing the file writer", e);
                }
                moveFile(writeToFile, renameFile);
            }
        }
    }
}

private void moveFile(String writeToFile, String renameFile) {
    try {
        FileUtils.moveFile(FileUtils.getFile(writeToFile), FileUtils.getFile(renameFile));
    } catch (IOException e) {
        LOGGER.info("Exception occured while moving file from writing to dat", e);
    }
}

这里extractCurrencyService是我提到的接口

界面:

public interface ExtractCurrencyService {

    public void extractCurrencyList(List<Currency> currency, Writer writer);

}

此方法定义由实现相同接口文件名的另一个文件完成:ExtractCurrencyServiceImpl。爪哇

public class ExtractCurrencyServiceImpl implements ExtractCurrencyService {
    private static final String SEP = "|";
    private static final String NEWLINE = "\n";

@Override
public void extractCurrencyList(List<Currency> currencyList, Writer writer) {
    if (currencyList != null) {
        currencyList.forEach(currency -> {
            String code = currency.getCode();
            String name = currency.getName() == null ? "" : currency.getName();
            Long noOfDecimals = currency.getNumberOfDecimals();
            RoundingMethodValue roundingMethod = currency.getRoundingMethod();
            boolean isDealCurrency = currency.isDealCurrency();
            String description = currency.getDescription() == null ? "" : currency.getDescription();
            try {
                writer.write(createCurrencyDataLine(code,
                                                    name,
                                                    noOfDecimals,
                                                    roundingMethod,
                                                    isDealCurrency,
                                                    description));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
    }
}

private String createCurrencyDataLine(String code,
                                      String name,
                                      Long noOfDecimals,
                                      RoundingMethodValue roundingMethod,
                                      boolean isdealCurrency,
                                      String description) {
    return code + SEP + name + SEP + noOfDecimals.toString() + SEP + roundingMethod.toString() + SEP
            + isdealCurrency + SEP + description + NEWLINE;
}

public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
    Map<Object, Boolean> map = new ConcurrentHashMap<>();
    return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}

}

这是测试文件:

@RunWith(MockitoJUnitRunner.class)
public class ExtractCurrencyDataTaskTest {

@Mock
private Currency mockCurrency;

@Mock
private ExtractCurrencyService mockExtractCurrencyService;

@Mock
private BufferedWriter mockBufferWriter;

@Mock
private Bean mockBean;

@InjectMocks
private ExtractCurrencyDataTask extractCurrencyDataTask;

@Test
public void writeCurrencyListToFileTest() {
    List<Currency> currencyList = new ArrayList();
    when(mockCurrency.getCode()).thenReturn("USD");
    when(mockCurrency.getNumberOfDecimals()).thenReturn((long) 2);
    when(mockCurrency.getRoundingMethod()).thenReturn(enum value);
    when(mockCurrency.isDealCurrency()).thenReturn(true);
    when(mockCurrency.getName()).thenReturn("US Dollars");
    when(mockCurrency.getDescription()).thenReturn("Currency Description");
    currencyList.add(mockCurrency);
    extractCurrencyDataTask.writeCurrencyListToFile(currencyList);
}
}

这是自动连线bean的配置

@Bean
public ExtractCurrencyService extractCurrencyService() {
    return new ExtractCurrencyServiceImpl();
}

正如您所看到的,这个过程的实际输出是,将在一个路径中创建一个文件,其中包含一些数据。在这个测试中,我模拟数据并将其传递给主文件。主文件是在各自路径中创建的文件,但文件中没有数据。 数据写入部分采用接口方式完成。这是我需要帮助的地方

提前谢谢


共 (1) 个答案

  1. # 1 楼答案

    您正在将模拟的ExtractCurrencyService注入到测试的类中。因此,测试是使用这个模拟实例而不是ExtractCurrencyServiceImpl运行的。当前的行为是ExtractCurrencyDataTask测试的类正在调用extractCurrencyService#extractCurrencyList,但是这个extractCurrencyService是一个模拟的,不是您真正的实现,因此调用已经完成,但它什么也不做

    如果您想要单元测试ExtractCurrencyDataTask,那么这没关系,但是您可能应该断言对extractCurrencyService#extractCurrencyList的调用是按照您期望的方式完成的

    如果您想要单元测试ExtractCurrencyServiceImpl,那么为这个类创建一个单元测试

    如果您想测试这两个类之间的交互,那么创建一个集成测试,其中ExtractCurrencyDataTask注入了ExtractCurrencyServiceImpl的真实实例,而不是模拟实例