You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JUnit 5编写测试用例验证单词计数程序的统计结果?

解决方案:重构代码+JUnit 5测试实现

首先你的代码所有逻辑都耦合在main方法里,依赖硬编码的文件路径,还直接修改原文件,这种结构完全无法做单元测试。必须先重构代码,把核心的单词统计逻辑和IO操作分离,才能高效编写测试用例。


第一步:重构原代码

把统计、排序、写入操作拆分成独立方法,用Map替代两个ArrayList(更高效且符合语义):

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

public class WordPopulation { // 修正类名大小写规范
    // 核心统计逻辑:接收输入流,返回单词-计数映射
    public static Map<String, Integer> countWords(InputStream inputStream) {
        Scanner scanner = new Scanner(inputStream);
        Map<String, Integer> wordCounts = new HashMap<>();

        while (scanner.hasNext()) {
            String word = scanner.next();
            wordCounts.put(word, wordCounts.getOrDefault(word, 0) + 1);
        }
        scanner.close();
        return wordCounts;
    }

    // 按计数降序排序统计结果
    public static List<Map.Entry<String, Integer>> sortByCountDesc(Map<String, Integer> wordCounts) {
        return wordCounts.entrySet()
                .stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .collect(Collectors.toList());
    }

    // 写入结果到文件
    public static void writeResults(String filePath, List<Map.Entry<String, Integer>> sortedResults) throws IOException {
        try (var fw = new java.io.FileWriter(filePath, true);
             var bw = new java.io.BufferedWriter(fw);
             var out = new java.io.PrintWriter(bw)) {
            for (var entry : sortedResults) {
                out.println();
                out.printf("%s occurred %d times%n", entry.getKey(), entry.getValue());
            }
        }
    }

    public static void main(String[] args) throws IOException {
        try (InputStream inputStream = new java.io.FileInputStream("theraven.txt")) {
            Map<String, Integer> counts = countWords(inputStream);
            List<Map.Entry<String, Integer>> sorted = sortByCountDesc(counts);
            writeResults("theraven.txt", sorted);
        }
    }
}

第二步:编写JUnit 5测试用例

通过ByteArrayInputStream模拟输入,避免依赖真实文件,覆盖各种测试场景:

import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;

class WordPopulationTest {

    @Test
    void countWords_emptyInput_returnsEmptyMap() {
        String input = "";
        try (var stream = new ByteArrayInputStream(input.getBytes())) {
            Map<String, Integer> result = WordPopulation.countWords(stream);
            assertTrue(result.isEmpty());
        }
    }

    @Test
    void countWords_singleWord_returnsCountOne() {
        String input = "hello";
        try (var stream = new ByteArrayInputStream(input.getBytes())) {
            Map<String, Integer> result = WordPopulation.countWords(stream);
            assertEquals(1, result.size());
            assertEquals(1, result.get("hello"));
        }
    }

    @Test
    void countWords_repeatedWords_returnsCorrectCounts() {
        String input = "hello hello world hello";
        try (var stream = new ByteArrayInputStream(input.getBytes())) {
            Map<String, Integer> result = WordPopulation.countWords(stream);
            assertEquals(2, result.size());
            assertEquals(3, result.get("hello"));
            assertEquals(1, result.get("world"));
        }
    }

    @Test
    void countWords_mixedCaseWords_treatsAsDifferent() {
        // 原代码区分大小写,若需忽略可在统计时转成小写
        String input = "Hello hello WORLD";
        try (var stream = new ByteArrayInputStream(input.getBytes())) {
            Map<String, Integer> result = WordPopulation.countWords(stream);
            assertEquals(3, result.size());
            assertEquals(1, result.get("Hello"));
            assertEquals(1, result.get("hello"));
            assertEquals(1, result.get("WORLD"));
        }
    }
}

关键说明

  1. 解耦IO与业务逻辑:把统计逻辑从文件读取/写入中分离,测试时用内存流模拟输入,无需操作真实文件
  2. 场景覆盖:测试空输入、单单词、重复单词、大小写区分等典型场景,确保逻辑正确性
  3. 原代码优化点:原代码把排序放在循环内(每次循环都排序)是错误的,重构后改为排序一次再遍历

内容的提问来源于stack exchange,提问作者John Hendricks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 20:50:33