JUnit4 fail()就在这里,但是pass()在哪里?

时间:2010-10-27 17:53:44

标签: java junit

JUnit4库中有一个fail()方法。我喜欢它,但遇到缺少pass()方法,而该方法在库中不存在。为什么会这样?

我发现我可以使用assertTrue(true)代替但仍然看起来不合逻辑。

@Test
 public void testSetterForeignWord(){
  try {
   card.setForeignWord("");
   fail();
  } catch (IncorrectArgumentForSetter ex){
  }

 // assertTrue(true);
 }

6 个答案:

答案 0 :(得分:62)

只要您的测试完成并通过,请致电 return 语句。

答案 1 :(得分:59)

只要测试没有抛出异常,它就会通过,除非你的@Test注释指定了预期的异常。我认为pass()可以抛出一个特殊的异常,JUnit总是将其解释为传递,以便使测试短路,但这会违反通常的测试设计(即假设成功,只有在断言失败时才会失败)并且,如果人们认为最好使用pass(),那么它将大大减慢一大堆通过测试(由于异常创建的开销)。失败的测试不应该是常态,所以如果他们有这样的开销就没什么大不了的。

请注意,您的示例可以像这样重写:

@Test(expected=IncorrectArgumentForSetter.class)
public void testSetterForeignWord("") throws Exception {
  card.setForeignWord("");
}

此外,您应该支持使用标准Java异常。您的IncorrectArgumentForSetter应该是IllegalArgumentException

答案 2 :(得分:5)

我认为这个问题需要更新的答案,因为这里的大多数答案都已经过时了。

首先是OP的问题:

我认为它很好地接受了引入"预期的例外情况"进入JUnit的概念是一个糟糕的举动,因为该异常可以在任何地方提出,并且它将通过测试。如果您抛出(并断言)非常特定于域的异常,它会起作用,但是当我处理需要绝对完美无瑕的代码时,我只抛出这些异常, - 大多数APIS只会抛出内置的异常例如IllegalArgumentExceptionIllegalStateException。如果两个调用你的make可以有效地抛出这些异常,那么@ExpectedException注释会对你的测试进行绿色调整,即使它是错误的行抛出异常!

对于这种情况,我写过一篇课程,我确信这里有很多其他人写过,这是一种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;
            }
        }
    }
}

如果抛出异常,此方法只会返回,允许您在测试中进行进一步的断言/验证。

使用java 8语法,您的测试看起来非常好。以下是我们使用该方法的模型的简单测试之一:

@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);
}

这些测试有点不稳定因为&#34;行为&#34;步骤并没有实际执行任何操作,但我认为其含义仍然相当明确。

还有一个名为catch-exception的maven上的小型库,它使用mockito风格的语法来验证是否会抛出异常。它看起来很漂亮,但我不是动态代理的粉丝。也就是说,语法是如此光滑,它仍然很诱人:

// 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;

最后,对于我遇到的这种情况,有一种方法可以在满足某些条件时忽略测试。

现在我正在努力通过一个名为JNA的java native-library-loading-library调用一些DLL,但是我们的构建服务器在ubuntu中。我喜欢尝试使用JUnit测试来推动这种开发 - 即使他们远离&#34;单位&#34;在此刻 - 。我想要做的是如果我在本地机器上运行测试,但如果我们在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();
}

答案 3 :(得分:3)

我也在为JUnit寻找pass方法,这样我就可以将某些不适用的测试短路(有集成测试,而不是纯单元测试)。太糟糕了,不存在。

幸运的是,有一种方法可以有条件地忽略测试,在我的情况下使用assumeTrue方法实际上更合适:

  

Assume.assumeTrue(isTestApplicable);

所以这里只有当isTestApplicable为true时才会执行测试,否则测试将被忽略。

答案 4 :(得分:2)

不需要pass方法,因为当测试代码中没有抛出AssertionFailedException时,单元测试用例将通过。

如果控制到达那一点,fail()方法实际上会抛出AssertionFailedException以使testCase失败。

答案 5 :(得分:1)

我认为这个问题是对测试执行过程有点误解的结果。在JUnit(和其他测试工具)中,每个方法计算结果,而不是每个断言调用。没有计数器可以跟踪已执行的通过/未通过assertX的次数。

JUnit分别执行每个测试方法。如果方法成功返回,则测试注册为“已通过”。如果发生异常,则测试注册为“失败”。在后一种情况下,两个子例程是可能的:1)JUnit断言异常,2)任何其他类型的异常。第一种情况下状态为“失败”,第二种情况为“错误”。

Assert类中,许多简写方法都可用于抛出断言异常。换句话说,Assert是JUnit异常的抽象层。

例如,这是GitHubassertEquals的源代码:

/**
 * 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异常,它将被JUnit捕获,并且

assertEqual("Oh?", "Same string", "Same string");

没有。

总而言之,像pass()这样的东西没有任何意义,因为它没有做任何事情。