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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4036144/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 10:47:52  来源:igfitidea点击:

JUnit4 fail() is here, but where is pass()?

javajunit

提问by Eugene

There is a fail()method in JUnit4 library. I like it, but experiencing a lack of pass()method which is not present in the library. Why is it so?

fail()JUnit4 库中有一个方法。我喜欢它,但缺乏pass()图书馆中没有的方法。为什么会这样?

I've found out that I can use assertTrue(true)instead but still looks unlogical.

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

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

 // assertTrue(true);
 }

采纳答案by ColinD

As long as the test doesn't throw an exception, it passes, unless your @Testannotation specifies an expected exception. I suppose a pass()could throw a special exception that JUnit always interprets as passing, so as to short circuit the test, but that would go against the usual design of tests (i.e. assume success and only fail if an assertion fails) and, if people got the idea that it was preferable to use pass(), it would significantly slow down a large suite of passing tests (due to the overhead of exception creation). Failing tests should not be the norm, so it's not a big deal if they have that overhead.

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

Note that your example could be rewritten like this:

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

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

Also, you should favor the use of standard Java exceptions. Your IncorrectArgumentForSettershould probably be an IllegalArgumentException.

此外,您应该赞成使用标准 Java 异常。你IncorrectArgumentForSetter应该是一个IllegalArgumentException.

回答by Ajay

There is no need for the pass method because when no AssertionFailedException is thrown from the test code the unit test case will pass.

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

The fail() method actually throws an AssertionFailedException to fail the testCase if control comes to that point.

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

回答by Horcrux7

Call returnstatement anytime your test is finished and passed.

return在您的测试完成并通过时调用语句。

回答by Groostav

I think this question needs an updated answer, since most of the answers here are fairly outdated.

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

Firstly to the OP's question:

首先是OP的问题:

I think its pretty well accepted that introducing the "expected excepetion" concept into JUnit was a bad move, since that exception could be raised anywhere, and it will pass the test. It works if your throwing (and asserting on) very domain specific exceptions, but I only throw those kinds of exceptions when I'm working on code that needs to be absolutely immaculate, --most APIS will simply throw the built in exceptions like IllegalArgumentExceptionor IllegalStateException. If two calls your making could potentitally throw these exceptions, then the @ExpectedExceptionannotation will green-bar your test even if its the wrong line that throws the exception!

我认为将“预期异常”概念引入 JUnit 是一个糟糕的举动,因为该异常可以在任何地方引发,并且它会通过测试,我认为这是很好的接受。它的工作原理,如果你的投掷(和主张上)非常特定领域的例外,但我只能扔这些类型的异常时,我工作的代码,需要是绝对完美的,--most APIS会简单地抛出内置的诸如异常IllegalArgumentExceptionIllegalStateException. 如果您进行的两次调用可能会抛出这些异常,那么@ExpectedException即使是抛出异常的错误行,注释也会绿条您的测试!

For this situation I've written a class that I'm sure many others here have written, that's an assertThrowsmethod:

对于这种情况,我编写了一个类,我相信这里的许多其他人都编写过,这是一种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;
            }
        }
    }
}

this method simply returns if the exception is thrown, allowing you to do further assertions/verification in your test.

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

with java 8 syntax your test looks really nice. Below is one of the simpler tests on our model that uses the method:

使用 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);
}

these tests are a little wonky because the "act" step doesn't actually perform any action, but I think the meaning is still fairly clear.

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

there's also a tiny little library on maven called catch-exceptionthat uses the mockito-style syntax to verify that exceptions get thrown. It looks pretty, but I'm not a fan of dynamic proxies. That said, there syntax is so slick it remains tempting:

maven 上还有一个叫做catch-exception 的小库,它使用 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;

Lastly, for the situation that I ran into to get to this thread, there is a way to ignoretests if some conidition is met.

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

Right now I'm working on getting some DLLs called through a java native-library-loading-library called JNA, but our build server is in ubuntu. I like to try to drive this kind of development with JUnit tests --even though they're far from "units" at this point--. What I want to do is run the test if I'm on a local machine, but ignore the test if we're on ubuntu. JUnit 4 does have a provision for this, called Assume:

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

回答by Dávid Horváth

I think that this question is a result of a little misunderstanding of the test execution process. In JUnit (and other testing tools) results are counted per method, not per assert call. There is not a counter, which keeps track of how many passed/failured assertXwas executed.

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

JUnit executes each test method separately. If the method returns successfully, then the test registered as "passed". If an exception occurs, then the test registered as "failed". In the latter case two subcase are possible: 1) a JUnit assertion exception, 2) any other kind of exceptions. Status will be "failed" in the first case, and "error" in the second case.

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

In the Assertclass many shorthand methods are avaiable for throwing assertion exceptions. In other words, Assertis an abstraction layer over JUnit's exceptions.

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

For example, this is the source code of assertEqualson GitHub:

例如,这是的源代码assertEquals的GitHub

/**
 * 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);
}

As you can see, in case of equality nothing happens, otherwise an excepion will be thrown.

如您所见,在相等的情况下什么也不会发生,否则将抛出异常。

So:

所以:

assertEqual("Oh!", "Some string", "Another string!");

simply throws a ComparisonFailureexception, which will be catched by JUnit, and

简单地抛出一个ComparisonFailure异常,它将被 JUnit 捕获,并且

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

does NOTHING.

什么也没做。

In sum, something like pass()would not make any sense, because it did not do anything.

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

回答by Sebastian K

I was looking for passmethod for JUnit as well, so that I could short-circuit some tests that were not applicable in some scenarios (there are integration tests, rather than pure unit tests). So too bad it is not there.

我也在寻找passJUnit 的方法,以便我可以短路一些在某些场景中不适用的测试(有集成测试,而不是纯单元测试)。太糟糕了,它不在那里。

Fortunately, there is a way to have a test ignored conditionally, which actually fits even better in my case using assumeTruemethod:

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

Assume.assumeTrue(isTestApplicable);

Assume.assumeTrue(isTestApplicable);

So here the test will be executed only if isTestApplicable is true, otherwise test will be ignored.

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