Java测试预期=异常失败,出现断言错误

Java测试预期=异常失败,出现断言错误,java,exception,junit,Java,Exception,Junit,我对一个测试用例有问题 正在测试的方法有一个try/catch,它捕获了一个MalformedURLException,但在测试过程中,由于Junit AssertionError期望出现一个MalformedURLException,我得到了一个失败。但我不知道它到底在扔什么!这是我的代码(在eclipse中创建为MWE) 我想测试的方法 public void throwMalFormedURLException(){ String s = new String("www.goog

我对一个测试用例有问题

正在测试的方法有一个try/catch,它捕获了一个
MalformedURLException
,但在测试过程中,由于Junit AssertionError期望出现一个MalformedURLException,我得到了一个失败。但我不知道它到底在扔什么!这是我的代码(在eclipse中创建为MWE)

我想测试的方法

public void throwMalFormedURLException(){

    String s = new String("www.google.com");

    try{
        url = new URL(s);
    }catch (Exception e){
        e.printStackTrace();
        e.getClass();
        e.getCause();
    }


}
试验方法

@Test (expected = MalformedURLException.class)
public void testThrowMalFormedURLException() {
    MWE testClass = new MWE();
    testClass.throwMalFormedURLException();
    System.out.println("End of test");
}
这是控制台中的输出

测试结束错误详细信息为:java.net.malformedurexception:无协议:www.google.com
在java.net.URL.(URL.java:593)
在java.net.URL.(URL.java:490)
在java.net.URL.(URL.java:439)
在MWE.throwmalformedurexception(MWE.java:12)
testMWE.testThrowMalFormedURLException(testMWE.java:12)

在Junit控制台中,它说:

java.lang.AssertionError:预期异常:java.net.MalformedURLException

但是Junit报告失败,尽管控制台告诉我有一个畸形的DurLexception

这次考试我做错了什么

谢谢你的想法


David

您正在捕获异常,因此不会抛出该异常

如果您的目的是测试您是否捕获了异常并将其正确地转发回“用户”,那么您应该专门为此创建测试。您可能不希望在单元测试中使用UI元素,因此这是一个抽象和DI有很多价值的地方。一种简单的方法是创建一个模拟对象,该对象将侦听错误消息,并在收到消息时标记一个标志。单元测试触发错误,如果设置了标志,则通过。在抛出异常之前,还应该进行否定测试或断言未设置该标志


*测试UI也是一个好主意,但可能有点慢。有各种各样的工具来实现自动化。它通常属于不同的测试阶段。您确实希望单元测试速度非常快,以便能够非常频繁地运行它们。

您已经编写了无法测试的生产代码。更具体地说:这段代码从一开始就没有任何“以编程方式”可观察到的副作用

意思:当您编写“生产代码”时,方法中的代码可以做三件可以观察到的事情:

  • 对作为测试类字段的对象进行方法调用
  • 返回一些值
  • 抛出异常
  • 对于这些选项中的每一个,您都可以编写测试代码:

  • 使用依赖项注入,您可以将一个模拟的对象放入被测试的类中。然后可以检查在模拟对象上是否调用了预期的方法;使用您期望的参数
  • 将调用该方法得到的结果与预期值进行比较
  • 您可以使用
    expected
    来确保引发了特定的异常
  • 当你看你的代码时;你可以看到:这一切都没有。它仅对在方法中创建的对象进行操作。它不返回任何值。而且,最重要的是:它不会抛出异常

    长话短说:捕获的异常不是“离开”该方法。它在那里被捕获,方法正常结束。打印捕获异常的详细信息并不能改变这一点

    因此,您必须做的第一件事是:从生产代码中删除整个try/catch

    如果您想进行更具体的测试,您可以执行以下操作:

    @Test
    public void testException() {
      try { 
        new MWE().throwMalFormedURLException();
        fail("should have thrown!");
      } catch ( MalFormedURLException me ) {
        assertThat(me.getMessage(), containsString("whatever"));
      }
    
    上述:

  • 未引发异常时失败
  • 引发MalFormedURLException以外的任何其他异常时失败
  • 允许您检查抛出异常的进一步属性

  • 这是一个有效的测试失败。测试断言,通过调用
    throwMalFormedURLException()
    将抛出
    MalformedURLException
    ,但由于捕获了异常,它不会抛出异常,因此测试失败。

    好吧,所以我觉得很傻,如何测试实际发生的异常?由于我想确保捕获到这些类型的错误,因此我可以向我的用户发送适当的消息。很难给出准确的答案,因为我不知道应用程序的详细信息,但简而言之,当捕获异常时,我将创建一个“向用户发送错误消息”的测试。为了更好地衡量,请编写一个测试,验证在未引发异常时不会发送此类消息。如果您将其作为一组点添加到回复中,我将接受您的解决方案。我必须承认这是我的系统的顶端,但是我可以很容易地在应该创建的“消息窗口”中捕捉到错误。ThanksI补充了更多细节。如果您不确定如何进行模拟,我可以稍后提供一个示例。谢谢您提供的额外信息。稍后我会研究嘲弄,但现在我有足够的时间来解决我的问题。我将在另一个“show a message to the user”类中捕获该方法,该类可以从我的捕获中调用,并将所需的异常传递给它,以及该消息(然后我可以对这两个消息进行测试)。感谢您的回复,我给您一个+1,因为在上面@Jimmy的响应之后,我已经在代码中给出了+1。感谢您的输入,因为它通过遵循您的示例使我的最终代码更清晰。