Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java JUnit4 fail()在这里,但是pass()在哪里?_Java_Junit - Fatal编程技术网

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

Java JUnit4 fail()在这里,但是pass()在哪里?,java,junit,Java,Junit,JUnit4库中有一个fail()方法。我喜欢它,但缺少库中不存在的pass()方法。为什么会这样 我发现我可以使用assertTrue(true)来代替,但看起来仍然不符合逻辑 @Test public void testSetterForeignWord(){ try { card.setForeignWord(""); fail(); } catch (IncorrectArgumentForSetter ex){ } // assertTrue(true);

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

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

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

 // assertTrue(true);
 }

只要测试没有抛出异常,它就会通过,除非
@test
注释指定了预期的异常。我假设一个
pass()
会抛出一个JUnit总是将其解释为通过的特殊异常,从而使测试短路,但这与通常的测试设计背道而驰(即假设成功,只有在断言失败时才会失败),如果人们认为最好使用
pass()
,这将大大降低通过测试的大型套件的速度(由于异常创建的开销)。测试失败不应该成为常态,所以如果他们有这样的开销,那也没什么大不了的

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

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

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

不需要pass方法,因为当没有从测试代码抛出断言failedeexception时,单元测试用例将通过


fail()方法实际上抛出了一个断言FailedException,如果控制达到该点,则会使测试用例失败。

在测试完成并通过时调用
返回
语句。

我认为这个问题需要更新答案,因为这里的大多数答案都相当过时

首先,关于OP的问题:

我认为,在JUnit中引入“预期异常”概念是一个错误的举动,这一点已经被广泛接受,因为该异常可以在任何地方提出,并且它将通过测试。如果您抛出(并断言)非常特定于域的异常,它是有效的,但我只在处理需要绝对完美的代码时抛出这些类型的异常,-大多数API只会抛出内置异常,如
IllegalArgumentException
IllegalArgumentException
。如果您发出的两个调用可能会引发这些异常,那么
@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;
            }
        }
    }
}
这些测试有点不可靠,因为“act”步骤实际上没有执行任何操作,但我认为其含义仍然相当清楚

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本机库加载库调用一些DLL,但我们的构建服务器在ubuntu中。我喜欢尝试用JUnit测试来驱动这种开发——尽管在这一点上它们离“单元”很远。我想做的是,如果我在本地机器上运行测试,但是如果我们在ubuntu上则忽略测试。JUnit4对此有一个规定,称为
假设

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

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

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

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

例如,这是上的
assertEquals
的源代码:

如您所见,在相等的情况下不会发生任何事情,否则将抛出一个例外

因此:

只需抛出一个
comparisonfail
异常,JUnit将捕获该异常,然后

assertEqual("Oh?", "Same string", "Same string");
什么也不做


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

我也在为JUnit寻找
pass
方法,这样我就可以短路一些在某些场景中不适用的测试(有集成测试,而不是纯粹的单元测试)。可惜它不在那里

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

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;
            }
        }
    }
}
假设。假设为真(不适用)


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

fail()方法和assertX()方法实际上只是抛出一个断言错误,这会导致测试方法不干净地退出。这就是为什么一个成功的返回表示成功…-1-pass()方法不是什么都不做-它会立即退出测试,没有异常。在大多数情况下,这实际上相当于return语句(除了预期的异常、超时等)。@grigory:您是对的,
pass()
方法不能什么都不做,以免调用后测试可能失败。所以我删除了那句话。我真是太感谢你了,帮助我摆脱了很多挫折+1.
assertEqual("Oh!", "Some string", "Another string!");
assertEqual("Oh?", "Same string", "Same string");