我知道完成它的一种方法是:
@Test
public void foo() {
try {
// execute code that you expect not to throw Exceptions.
} catch(Exception e) {
fail("Should not have thrown any exception");
}
}
有没有更简洁的方法来完成这个任务?(可能使用Junit的@Rule
注解?)
我知道完成它的一种方法是:
@Test
public void foo() {
try {
// execute code that you expect not to throw Exceptions.
} catch(Exception e) {
fail("Should not have thrown any exception");
}
}
有没有更简洁的方法来完成这个任务?(可能使用Junit的@Rule
注解?)
JUnit 5(Jupiter)提供三个函数来检查异常的存在/缺失:
assertAll()
断言所有提供的executables
都不会抛出异常。
assertDoesNotThrow()
断言执行
提供的executable
/supplier
不会抛出任何类型的异常。
自JUnit 5.2.0(2018年4月29日)起,此函数可用。
assertThrows()
断言执行提供的executable
将引发expectedType
类型的异常,并返回exception。
package test.mycompany.myapp.mymodule;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
class MyClassTest {
@Test
void when_string_has_been_constructed_then_myFunction_does_not_throw() {
String myString = "this string has been constructed";
assertAll(() -> MyClass.myFunction(myString));
}
@Test
void when_string_has_been_constructed_then_myFunction_does_not_throw__junit_v520() {
String myString = "this string has been constructed";
assertDoesNotThrow(() -> MyClass.myFunction(myString));
}
@Test
void when_string_is_null_then_myFunction_throws_IllegalArgumentException() {
String myString = null;
assertThrows(
IllegalArgumentException.class,
() -> MyClass.myFunction(myString));
}
}
assertDoesNotThrow(myObject::myValidationFunction);
- AlexgetUserById()
,它将返回一个用户,总共有3个工作单元。@Test(expected = IllegalArgumentException.class)
注释捕获的IllegalArgumentException
。existingUserById_ShouldReturn_UserObject
。如果此方法失败(例如:抛出异常),则您知道出了问题,可以开始挖掘。nonExistingUserById_ShouldThrow_IllegalArgumentException
),该测试使用错误输入并期望异常,您可以查看您的方法是否按照其所应该处理错误的输入。throws IllegalArgumentException
即可。最终你想要的是,如果出现异常,你的测试会变成红色。好吧,你知道吗?你不需要编写 fail()
。正如 @Jeroen Vannevel 所写:“如果抛出异常,测试将自动失败”。 - Amedee Van Gasse我因SonarQube的规则"squid:S2699"偶然发现了这个问题:“在此测试用例中至少添加一个断言。”
我有一个简单的测试,其唯一目的是在不抛出异常的情况下进行。
请考虑以下简单代码:
public class Printer {
public static void printLine(final String line) {
System.out.println(line);
}
}
测试该方法可以添加什么样的断言?虽然你可以在它周围加上try-catch,但那只是代码膨胀。
解决方案来自于JUnit本身。
如果没有抛出异常并且您想明确说明这种行为,请像下面的示例中一样添加expected
:
@Test(expected = Test.None.class /* no exception expected */)
public void test_printLine() {
Printer.printLine("line");
}
Test.None.class
是预期值的默认值。
如果您导入了org.junit.Test.None
,然后您可以写如下代码:
@Test(expected = None.class)
您可能会发现这更易读。
@Test
注解并不能解决SonarQube问题。 - David ConradassertDoesNotThrow(() -> Printer.printLine("line"));
- Ankush对于JUnit 5之前的版本:
使用AssertJ fluent assertions 3.7.0:
Assertions.assertThatCode(() -> toTest.method())
.doesNotThrowAnyException();
更新:
JUnit 5 引入了 assertDoesNotThrow()
断言,所以我更喜欢使用它而不是向您的项目添加额外的依赖项。有关详细信息,请参见此答案。
class MyAssertions{
public static void assertDoesNotThrow(FailingRunnable action){
try{
action.run()
}
catch(Exception ex){
throw new Error("expected action not to throw, but it did!", ex)
}
}
}
@FunctionalInterface interface FailingRunnable { void run() throws Exception }
然后你的代码就变得简单了:
@Test
public void foo(){
MyAssertions.assertDoesNotThrow(() -> {
//execute code that you expect not to throw Exceptions.
}
}
//setup
Component component = new Component();
//act
configure(component);
//assert
/*assert does not throw*/{
component.doSomething();
}
最后,使用Kotlin这门语言,我最近深深爱上了它:
fun (() -> Any?).shouldNotThrow()
= try { invoke() } catch (ex : Exception){ throw Error("expected not to throw!", ex) }
@Test fun `when foo happens should not throw`(){
//...
{ /*code that shouldn't throw*/ }.shouldNotThrow()
}
虽然你可以根据自己的喜好灵活表达,但我一直是流畅断言(Fluent Assertions)的粉丝。
关于
你的方法不对。只需测试你的功能:如果抛出异常,则测试将自动失败。如果没有抛出异常,则所有测试都应该通过。
原则上是正确的,但结论是错误的。
Java允许使用异常控制流程。在像Double.parseDouble
和Paths.get
这样的API中,JRE运行时本身就使用了NumberFormatException
和InvalidPathException
等异常。
假设你已经编写了一个验证Double.ParseDouble
数字字符串的组件,可能使用了正则表达式,可能使用了手写解析器,或者可能嵌入了其他限制双精度范围的域规则,如何最好地测试此组件?我认为一个明显的测试是断言当解析结果字符串时不会抛出异常。使用上述assertDoesNotThrow
或/*comment*/{code}
代码块编写此测试,类似于:
@Test public void given_validator_accepts_string_result_should_be_interpretable_by_doubleParseDouble(){
//setup
String input = "12.34E+26" //a string double with domain significance
//act
boolean isValid = component.validate(input)
//assert -- using the library 'assertJ', my personal favourite
assertThat(isValid).describedAs(input + " was considered valid by component").isTrue();
assertDoesNotThrow(() -> Double.parseDouble(input));
}
Theories
或Parameterized
对input
参数进行参数化,以便您可以更轻松地将此测试用于其他输入。或者,如果您想要更加奇特一些,您可以选择测试生成工具(和这个)。TestNG对参数化测试的支持更好。@Test(expectedException=IllegalArgumentException.class)
,因为这种异常太过宽泛。如果您的代码发生了变化,使得被测试组件的构造函数有了if(constructorArgument <= 0) throw IllegalArgumentException()
,而您的测试为该参数提供了0,因为这很方便——这是非常常见的,因为生成良好的测试数据是一个出奇的难题——那么您的测试将会是绿色的,即使它什么都没有测试到。这样的测试比无用还要糟糕。Assert.assertThrows
来检查某些代码是否引发异常。 - MageWind如果你很不幸地发现你的代码中有所有的错误,那么你只能愚蠢地做如下操作:
class DumpTest {
Exception ex;
@Test
public void testWhatEver() {
try {
thisShouldThrowError();
} catch (Exception e) {
ex = e;
}
assertEquals(null,ex);
}
}
Exception ex
应该先赋值为 = null;
。 - DeneesAwaitility
的untilAsserted(ThrowingRunnable assertion)
中进行断言。我调用的方法一开始总是会抛出异常,但我想断言它最终会停止这样做(根据Awaitility的参数)。 - Ubeogesh虽然这篇文章已经6年了,但是JUnit世界已经发生了很多变化。使用JUnit5,你现在可以使用
org.junit.jupiter.api.Assertions.assertDoesNotThrow()
例:
public void thisMethodDoesNotThrowException(){
System.out.println("Hello There");
}
@Test
public void test_thisMethodDoesNotThrowException(){
org.junit.jupiter.api.Assertions.assertDoesNotThrow(
()-> thisMethodDoesNotThrowException()
);
}
希望这能帮助使用Junit5新版本的人们。
Awaitility
的untilAsserted(ThrowingRunnable assertion)
内部执行此操作。目前测试的系统正在我的提供的ThrowingRunnable
上抛出特定的异常,但我希望它有一些时间停止这样做。但是,如果它抛出不同的异常,我希望测试立即失败。 - Ubeogesh测试一个像无返回值方法一样的场景
void testMeWell() throws SomeException {..}
避免抛出异常:
Junit5
assertDoesNotThrow(() -> {
testMeWell();
});
AssertJ 可以处理这种情况:
assertThatNoException().isThrownBy(() -> System.out.println("OK"));
请查看文档以获取更多信息https://assertj.github.io/doc/#assertj-core-exception-assertions-no-exception