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

JUnit测试StudentGradeGenerator错误信息断言异常问题咨询

JUnit测试StudentGradeGenerator.ValidateMark方法时错误信息断言失败

问题描述

我正在用JUnit测试ProgramFunctions包下StudentGradeGenerator类的ValidateMark方法,该方法会在输入不合法时设置对应错误信息。测试时验证错误信息是否正确,但对比预期错误信息数组时出现断言失败:当测试输入为"0"(对应索引2)时,断言提示预期值为"Line (0): Final Mark must be a value between 0 and 60!",但实际获取的错误信息为空字符串——尽管预期数组FinalMarkExpectedErrorSet的索引2位置是空字符串,我怀疑数组未被正确遍历。

测试类代码

package ProjectUnitTest;

import static org.junit.jupiter.api.Assertions.*;

import java.net.URL;

import ProgramFunctions.StudentGradeGenerator;

import org.junit.jupiter.api.Test;


class StudentGradeGeneratorTest {

@Test
    void TestFinalMark() {
        int expectedIndex = 0;
        String[] MarkInputs = new String[] { "d20", "-10", "0", "55", "60", "70" };
        int[] exepected = new int[] { -1, -1, 0, 55, 60, -1 };
    
    String[] FinalMarkExpectedErrorSet =new String[]{
          "Line (0): Final Mark must be of type int!",
          "Line (0): Final Mark must be a value between 0 and 60!",
          "",
          "",
          "",
          "Line (0): Final Mark must be a value between 0 and 60!"
          };
    
    for (var mark : MarkInputs) {
        int actual = StudentGradeGenerator.ValidateMark("Final Mark", mark, 60);
        assertEquals(exepected[expectedIndex], actual,String.format("mark::%s => Returning Error in validating Final Mark Function",mark));
        assertEquals(StudentGradeGenerator.getError(),FinalMarkExpectedErrorSet[expectedIndex],String.format("mark::%s,index::%d =>Error in::Error set in Final Mark Function",mark,expectedIndex));
        expectedIndex++;
    }

}

被测试类代码

package ProgramFunctions;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.String;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.Vector;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

public class StudentGradeGenerator {

/*the error variable is used to store the error 
 *raised by any function. which is used later to in the gui
 *to display it to the user.
 */
private static String _error="";
/*the ErrorlineNumber is used to display the 
 * line of the error.
 * it's first initalized to zero, then in the 
 * InputParse function the variable is increased for every
 * line being parsed by one. 
 */
private static int ErrorlineNumber=0;

/*function to validate if the mark is:
 * 1) of type int.
 * 2) value between 0 and a maximum mark.
 */
public static int ValidateMark(String MarkName,String mark,int MaxMark)
{
    try {
        /*parse the string number in case of :
         * success: this means that mark is of type int
         * (then the value will be checked if it's between 0 & MaxMark).
         * fail: an exception will occur. 
         */
        int Mark =Integer.parseInt(mark);

        /*check if the mark between 0 & MaxMark:
         * if it's : the value is correct and will be returned.
         * else: an error will be raised and the function will return with value -1.
         */
        if(Mark>=0 && Mark<=MaxMark) return Mark;

        _error ="Line ("+ErrorlineNumber+"): "+MarkName +" must be a value between 0 and "+ MaxMark +"!";
        return -1;

    }
    catch(Exception e)
    {
        /*if we reached here then that's means the mark wasn't of type int.
         * first raise an error then return with value -1.
         */
        _error ="Line ("+ErrorlineNumber+"): "+MarkName+" must be of type int!";
        return -1;
    }
}
    public static String getError(){
    return _error;
}
}

错误输出

AssertionFailedError: mark::0,index::٢ =>Error in::Error set in Final Mark Function ==> expected: <Line (0): Final Mark must be a value between 0 and 60!> but was: <>

问题分析与解决方案

核心问题

  1. assertEquals参数顺序颠倒:JUnit的assertEquals方法要求预期值在前,实际值在后,当前代码把实际错误信息(StudentGradeGenerator.getError())放在第一个参数,预期值(FinalMarkExpectedErrorSet[expectedIndex])放在第二个,导致断言逻辑错误,且错误提示的预期/实际值完全搞反。

  2. 静态_error变量未重置:ValidateMark方法在输入合法时直接返回结果,没有清空静态变量_error的内容,导致当前测试用例的错误信息残留了上一次测试的结果(比如输入"0"时,_error还是上一次输入"-10"设置的错误字符串)。

修复步骤

1. 修正assertEquals参数顺序

将错误信息断言的参数顺序调整为预期值在前,实际值在后:

assertEquals(FinalMarkExpectedErrorSet[expectedIndex], StudentGradeGenerator.getError(), 
             String.format("mark::%s,index::%d =>Error in::Error set in Final Mark Function", mark, expectedIndex));

2. 重置静态_error变量

修改ValidateMark方法,在每次调用时先清空错误信息,避免残留:

public static int ValidateMark(String MarkName,String mark,int MaxMark)
{
    _error = ""; // 每次调用先清空错误信息
    try {
        int Mark = Integer.parseInt(mark);
        if(Mark>=0 && Mark<=MaxMark) return Mark;

        _error ="Line ("+ErrorlineNumber+"): "+MarkName +" must be a value between 0 and "+ MaxMark +"!";
        return -1;
    }
    catch(Exception e)
    {
        _error ="Line ("+ErrorlineNumber+"): "+MarkName+" must be of type int!";
        return -1;
    }
}

额外优化建议

静态变量_error和ErrorlineNumber会导致测试用例之间的状态干扰(比如连续测试时,上一次的错误信息会影响下一次),建议将这些变量改为实例变量,通过创建StudentGradeGenerator实例来调用方法,而非使用静态方法,提升代码的可测试性和线程安全性。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 14:20:00