关于java:了解JUnit 5中的异常测试

Understanding Exception tests in JUnit 5

我已经离开Java一段时间了,JUnit 5同时出现了。我正在尝试将一些现有的JUnit 4测试重写为JUnit 5,但我正在努力解决如何处理抛出异常的方法。例如,我有一个名为LocalizationUtils的类(不要与API中找到的任何其他类混淆),它有一个名为getResources()的方法,它需要一个非空的基本名称作为输入并返回如果可以找到相应的资源包。如果基本名称为null,则抛出NullPointerException;如果无法找到资源束,则抛出MissingResourceException。这是代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    static public ResourceBundle getResources(String baseName) throws NullPointerException, MissingResourceException {

    if (baseName == null) {
        final String msg ="The base name cannot be null.";
        NullPointerException npExcp = new NullPointerException(msg);
        Logger logger = Logger.getLogger(CLASS_NAME);
        logger.log(Level.SEVERE, msg, npExcp);
        throw npExcp;
        }

    /* Get the resource bundle for the current locale. */
    try {
        return(ResourceBundle.getBundle(baseName));
        }
    catch (MissingResourceException mrExcp) {
        String msg ="Unable to find resources for base name" + baseName +".";
        Logger logger = Logger.getLogger(CLASS_NAME);
        logger.log(Level.SEVERE, msg, mrExcp);
        throw mrExcp;
        }

}

JUnit 5的手册给出了处理异常的示例:

1
2
3
4
5
6
7
@Test
void exceptionTesting() {
    Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
        throw new IllegalArgumentException("a message");
    });
    assertEquals("a message", exception.getMessage());
}

这个例子对我来说毫无意义。它似乎是凭空消息创造了一条"消息"的例外。我没有看到它实际上正在执行任何类或方法。对于这应该如何工作没有真正的解释,所以可能/可能这只是我的误解。

为了编写一个实际执行我的代码并强制发生错误的测试,我编写了这个JUnit 5测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Test
void testGetResourcesString() {

    //Normal cases

    //Exception - input parameter is null
    /* Verify that the expected type of exception was thrown. */
    Throwable npExcp = assertThrows(NullPointerException.class, () -> {
        LocalizationUtils.getResources(null);
    });  
    /* Verify that the exact right error message was generated. */  
    assertEquals("The base name cannot be null.", npExcp.getMessage());


    //Exception - all input is non-null but resource bundle not found
    /* Verify that the expected type of exception was thrown. */
    Throwable mrExcp = assertThrows(MissingResourceException.class, () -> {
        LocalizationUtils.getResources("foo");
    });  
    /* Verify that the exact right error message was generated. */
    assertEquals("Can't find bundle for base name foo, locale en_CA", mrExcp.getMessage());    
}

此测试中的所有内容都按照我的预期工作,它似乎比手册中的示例更合乎逻辑,因为它实际上执行了一个类和方法来引发异常。我还想确保生成了正确的消息,因为很容易想象一个带有多个输入参数的方法,而不是只有一个任何参数为null的方法应该抛出一个带有唯一消息的异常。简单地确定抛出了正确的异常对我来说似乎不够:我觉得我想确保创建了正确的消息,以便我知道代码正在对几个正确的null参数做出反应。

我不愿意相信手册错了;我想一个由几位经验丰富的开发人员组成的团队编写并非常小心。任何拥有比我更多JUnit 5知识的人 - 必须是所有使用过JUnit 5的人 - 确认手册中的示例是正确的,如果是,那么当没有类或方法名称时它应该如何工作提供?


该示例确实称为"方法"。 lambda表达式() -> {...}定义了一个匿名方法。 它包含一个语句:throw new IllegalArgumentException

请参阅java语言规范

1
2
3
4
5
6
7
8
9
() -> {}                // No parameters; result is void
() -> 42                // No parameters, expression body
() -> null              // No parameters, expression body
() -> { return 42; }    // No parameters, block body with return
() -> { System.gc(); }  // No parameters, void block body
(int x) -> x+1              // Single declared-type parameter
(int x) -> { return x+1; }  // Single declared-type parameter
(x) -> x+1                  // Single inferred-type parameter
 x  -> x+1                  // Parens optional for single inferred-type case

所以这个例子有一个方法,它只是抛出一个异常。

1
() -> { throw new IllegalArgumentException("a message"); }

在您的代码中,您实际上是在定义一个没有参数的方法,使用一个参数调用您的方法。

1
() -> { LocalizationUtils.getResources(null); }