JUnit4 fail()在这里,但是pass()在哪里?
JUnit4库中有一个fail()
方法。 我喜欢它,但遇到缺乏pass()
方法,这是不存在于图书馆。 为什么这样?
我发现,我可以使用assertTrue(true)
来代替,但仍然看起来不合逻辑。
@Test public void testSetterForeignWord(){ try { card.setForeignWord(""); fail(); } catch (IncorrectArgumentForSetter ex){ } // assertTrue(true); }
只要testing不会抛出exception,它就会通过,除非您的@Test
注释指定了预期的exception。 我猜想pass()
可能会抛出JUnit总是解释为传递的特殊exception,以便短路testing,但这样做会违背testing的常规devise(即假设成功,只有在断言失败时才会失败)如果人们认为最好使用pass()
,那么会大大减慢大量的通过testing(由于exception创build的开销)。 失败的testing不应该成为标准,所以如果他们有这样的开销,这不是什么大问题。
请注意,您的示例可以像这样重写:
@Test(expected=IncorrectArgumentForSetter.class) public void testSetterForeignWord("") throws Exception { card.setForeignWord(""); }
另外,您应该倾向于使用标准的Javaexception。 您的IncorrectArgumentForSetter
可能应该是一个IllegalArgumentException
。
在testing完成并通过时调用return
语句。
没有必要使用pass方法,因为当testing代码抛出AssertionFailedException时,unit testing用例会通过。
fail()方法实际上会引发一个AssertionFailedException,如果控件到达那个地方,testCase就会失败。
我认为这个问题需要一个更新的答案,因为这里的答案大部分已经过时了。
首先是OP的问题:
我认为它很好地接受了将“期望的exceltion”概念引入JUnit是一个坏的举动,因为这个exception可以在任何地方提出,并且会通过testing。 如果你抛出(并声明)特定领域的exception,但是我只在抛出那些需要绝对完美的代码时才抛出这些exception,大多数情况下,APIS只会抛出内置的exception,比如IllegalArgumentException
或IllegalStateException
。 如果两个调用你的做出可能有力地抛出这些exception,那么@ExpectedException
注释将绿色禁止你的testing,即使它的引发exception的错误行!
对于这种情况,我写了一个类,我相信这里有很多其他人写的,这是一个assertThrows
方法:
public class Exceptions { private Exceptions(){} public static void assertThrows(Class<? extends Exception> expectedException, Runnable actionThatShouldThrow){ try{ actionThatShouldThrow.run(); fail("expected action to throw " + expectedException.getSimpleName() + " but it did not."); } catch(Exception e){ if ( ! expectedException.isInstance(e)) { throw e; } } } }
这个方法只是在抛出exception的时候返回,这样你可以在你的testing中做进一步的断言/validation。
用java 8语法你的testing看起来非常好。 下面是我们使用该方法的模型的一个更简单的testing:
@Test public void when_input_lower_bound_is_greater_than_upper_bound_axis_should_throw_illegal_arg() { //setup AxisRange range = new AxisRange(0,100); //act Runnable act = () -> range.setLowerBound(200); //assert assertThrows(IllegalArgumentException.class, act); }
这些testing有点过分,因为“行为”步骤实际上并没有采取任何行动,但我认为其意义还是相当清楚的。
maven上还有一个名为catch-exception的小型库,它使用mockito风格的语法来validation抛出的exception。 它看起来很漂亮,但我不是dynamic代理的粉丝。 这就是说,语法如此华丽,它仍然是诱人的:
// given: an empty list List myList = new ArrayList(); // when: we try to get the first element of the list // then: catch the exception if any is thrown catchException(myList).get(1); // then: we expect an IndexOutOfBoundsException assert caughtException() instanceof IndexOutOfBoundsException;
最后,对于碰到这个线程的情况,如果遇到某些情况,可以忽略testing。
现在我正在通过名为JNA的Java本地库加载库来获取一些DLL,但是我们的构build服务器是在Ubuntu中。 我喜欢尝试用JUnittesting来推动这种发展 – 尽pipe在这一点上它们远离“单位”。 我想要做的是运行testing,如果我在本地机器上,但忽略testing,如果我们在Ubuntu上。 JUnit 4对此有一个规定,名为Assume
:
@Test public void when_asking_JNA_to_load_a_dll() throws URISyntaxException { //this line will cause the test to be branded as "ignored" when "isCircleCI" //(the machine running ubuntu is running this test) is true. Assume.assumeFalse(BootstrappingUtilities.isCircleCI()); //an ignored test will typically result in some qualifier being put on the results, //but will also not typically prevent a green-ton most platforms. //setup URL url = DLLTestFixture.class.getResource("USERDLL.dll"); String path = url.toURI().getPath(); path = path.substring(0, path.lastIndexOf("/")); //act NativeLibrary.addSearchPath("USERDLL", path); Object dll = Native.loadLibrary("USERDLL", NativeCallbacks.EmptyInterface.class); //assert assertThat(dll).isNotNull(); }
我认为这个问题是对testing执行过程有点误解的结果。 在JUnit(和其他testing工具)中,结果按每个方法进行计数,而不是每个断言调用。 没有一个计数器,logging有多less通过/失败的assertX
被执行。
JUnit分别执行每个testing方法。 如果方法返回成功,则testing注册为“通过”。 如果发生exception,则testing注册为“失败”。 在后一种情况下,可能有两个子情况:1)JUnit断言exception,2)任何其他types的exception。 在第一种情况下状态将是“失败”,在第二种情况下是“错误”。
在Assert
类中,许多简写方法可用于抛出断言exception。 换句话说, Assert
是JUnitexception的抽象层。
例如,这是GitHub上的assertEquals
的源代码:
/** * Asserts that two Strings are equal. */ static public void assertEquals(String message, String expected, String actual) { if (expected == null && actual == null) { return; } if (expected != null && expected.equals(actual)) { return; } String cleanMessage = message == null ? "" : message; throw new ComparisonFailure(cleanMessage, expected, actual); }
正如你所看到的,在平等的情况下什么都不会发生,否则就会被抛出。
所以:
assertEqual("Oh!", "Some string", "Another string!");
只是抛出了一个ComparisonFailure
exception,这将由JUnit和
assertEqual("Oh?", "Same string", "Same string");
什么也没做。
总之,类似pass()
东西没有任何意义,因为它没有做任何事情。
我也在为JUnit寻找pass
方法,这样我就可以将一些不适用于某些场景的testing(有集成testing,而不是纯粹的unit testing)进行短路。 如此糟糕,它不在那里。
幸运的是,有一种方法可以有条件地忽略testing,在我的情况下使用assumeTrue
方法实际上更适合:
Assume.assumeTrue(isTestApplicable);
所以这里只有在isTestApplicable为true时才会执行testing,否则testing将被忽略。