Java JUnit assertThrows中的可执行文件会发生什么情况?

Java JUnit assertThrows中的可执行文件会发生什么情况?,java,junit5,functional-interface,Java,Junit5,Functional Interface,我知道Junit5断言.assertThrows接受可执行类型的对象。因此,对于一个简单的示例,构造函数不能将空字符串作为名称参数: public Company(String aName, Calendar aFoundingDate) { if (aName == null || aName.length() == 0 || aName.length() > 50) { throw new IllegalArgumentException("Invalid na

我知道Junit5
断言.assertThrows
接受可执行类型的对象。因此,对于一个简单的示例,构造函数不能将空字符串作为名称参数:

public Company(String aName, Calendar aFoundingDate)
{
    if (aName == null || aName.length() == 0 || aName.length() > 50) {
        throw new IllegalArgumentException("Invalid name");
    }
    this.name = aName;
    foundingDate = aFoundingDate;
}
我可以编写这样的测试:

// Company constructor test
@Test
void testCompanyConstructor() {
    // Given
    String emptyName = "aabbe";
    Calendar validFoundingDate = Calendar.getInstance();
    validFoundingDate.set(2000, 1, 1);

    // Then
    assertThrows(IllegalArgumentException.class, () -> new Company(emptyName, validFoundingDate));
}
我想知道的是,可执行文件,即Lambda表达式会发生什么变化? JUnit是否对Lambda表达式调用execute(),并在这样做时,创建了名称为空的匿名company对象,并创建了异常

附件: 这些版本相当于:

// Company constructor test
@Test
void testCompanyConstructor() {
    // Given
    String emptyName = "";
    Calendar validFoundingDate = Calendar.getInstance();
    validFoundingDate.set(2000, 1, 1);

    // Then
    Executable executable = new Executable() {
        public void execute() {
            new Company(emptyName, validFoundingDate);
        }
    };
    assertThrows(IllegalArgumentException.class, executable);
    assertThrows(IllegalArgumentException.class, () -> new Company(emptyName, validFoundingDate));
}

是的,事情就是这样。JUnit在
try{…}catch(Throwable t){…}
block。如果捕获的异常属于指定类型,则一切正常。如果没有,则抛出断言错误。

当检查
assertThrows
的代码时,我们可以看到在
assertThrows::assertThrows
中有这样的代码:

try {
    executable.execute();
}
catch (Throwable actualException)
    if (expectedType.isInstance(actualException)) {
        return (T) actualException;
    }
    else {
        BlacklistedExceptions.rethrowIfBlacklisted(actualException);
        String message = buildPrefix(nullSafeGet(messageOrSupplier))
                + format(expectedType, actualException.getClass(), "Unexpected exception type thrown");
        throw new AssertionFailedError(message, actualException);
    }
}

因此,它基本上调用
可执行文件
,捕获可能抛出的
可丢弃文件
,并返回它。如果未引发异常或异常类型与预期不同,则断言将失败。

答案为“是”。确切地说:代码试图创建一个新的
公司
,但由于在对象构造过程中抛出了一个
异常
,因此
公司
永远不会被完全构造。JUnit将通过对其执行
run()
来执行您的
Runnable
实例。然后它会检查它是否抛出。如果它抛出给定的异常,测试就可以了。如果不是,它就失败了。是的,但是Java中没有匿名对象的概念。执行lambda后,只有Company对象不保存在引用中。