【问题标题】:Custom Java Exception Failing JUnit Test自定义 Java 异常未通过 JUnit 测试
【发布时间】:2017-03-19 02:24:42
【问题描述】:

我正在做一个 JUnit 测试,它接受一个 Person 并检查是否返回了 PersonException(我的自定义异常)。 PersonException 扩展了 Exception 并且 Person 有一个方法 SetDOB(),如果个人超过 100 岁,它会抛出 PersonException。到目前为止,异常打印在控制台中,这是应该的,但由于某种原因仍然无法通过测试。这是相关代码。

//JUnit Test
@Test(expected = PersonException.class)
public void testBadShieffer1() {
    Staff wrongShieffer = new Staff("Bob", "Lloyd", "Shnieffer",
        new Date(1737, 2, 25), "Shieffer Lane", "21277777778" /*PhoneNumber*/ ,
        "RadioMan@shieffer.shief",
        "Radio time.", 10, 500000.00, new Date(1991 + 1900, 1, 1), eTitle.MR);
    //This constructor calls SetDOB()
    fail("No PersonExceptions were thrown.");
}

//setDOB
public void setDOB(Date DOB) {
    try {
        if (((new Date()).getYear() + 1900) > DOB.getYear() + 100)
            throw new PersonException(this);
        else
            this.DOB = DOB;
    } catch (PersonException p) {
        System.out.println(p + " is over 100 years old!");
    }
}

//PersonException class
public class PersonException extends Exception {
    private Person p;

    public PersonException() {
        super();
    }

    public PersonException(String message) {
        super(message);
    }

    public PersonException(Person p) {
        super(p.getLastName());
        this.p = p;
    }

    public Person P() {
        return p;
    }
}

如果这有点冗长,我深表歉意,但我相信那里需要的一切都已存在。提前感谢您的帮助!

【问题讨论】:

  • 一个忠告,使用非常酷和好的 Java 8 time api (docs.oracle.com/javase/8/docs/api/java/time/…) 而不是非常糟糕和蹩脚的旧 Date api (stackoverflow.com/questions/1969442/…)。
  • 按照它的写法,看起来setDOB 永远不会抛出PersonException,因为在它被抛出之后,你会在setDOB 方法中捕获它。如果您最终发现异常,使用 (expected = PersonException.class) 的测试将永远不会通过。
  • 托马斯,感谢您的回复。这实际上也是我的猜测。虽然,我不确定如何在 try 语句中抛出异常而不捕获它。有什么建议吗?
  • 抱歉,您可以通过研究异常的概念来做到这一点。仅仅听到一些概念,然后将其放入您的代码中是不够的。你就像一个驾驶汽车的人,学会了如何加速;并且假设“也许我以后会想办法放慢速度”。我的意思是:不要反复试验。 学习和学习;例如从这里:docs.oracle.com/javase/tutorial/essential/exceptions/index.html

标签: java exception junit


【解决方案1】:

正如我在评论中所说,测试用例永远不会通过,因为抛出的异常也被同一方法捕获(这没有多大意义)。您可以通过两种方法之一来解决此问题,这取决于您要抛出哪种异常。无论在何处调用setDOB(),都需要捕获和处理Checked Exception。您可以通过将setDOB 更改为:

public void setDOB(Date DOB) throws PersonException {

    if (((new Date()).getYear() + 1900) > DOB.getYear() + 100) {
            throw new PersonException(this);
    }
    else {
        this.DOB = DOB;
    }
}

解决此问题的另一种方法是将PersonException 设为未经检查的异常。这种类型的异常不需要在调用视线时被捕获。您可以通过将setDOB() 更改为:

 public void setDOB(Date DOB) {

    if (((new Date()).getYear() + 1900) > DOB.getYear() + 100) {
            throw new PersonException(this);
    }
    else {
        this.DOB = DOB;
    }
}

然后让PersonException 扩展RuntimeException,而不是Exception,像这样:

public class PersonException extends RuntimeException

为了让您的单元测试按原样通过,Unchecked 方法会起作用。您可以了解有关异常的更多信息here

【讨论】:

  • 我决定采用 Checked 方法。起初我很不情愿,因为我需要将 throws PersonException 添加到几个方法中,但在这种情况下,这似乎是更合乎逻辑的处理方式。感谢您提供如此丰富的信息和快速响应!
猜你喜欢
  • 2013-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 2020-05-13
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多