代码之家  ›  专栏  ›  技术社区  ›  Christopher Parker

TestNG:如何测试强制异常?

  •  17
  • Christopher Parker  · 技术社区  · 15 年前

    我想编写一个TestNG测试,以确保在特定条件下抛出异常,如果没有抛出异常,则测试失败。有没有一个简单的方法来做到这一点,而不必创建一个额外的布尔变量?

    有关此主题的相关博客文章: http://konigsberg.blogspot.com/2007/11/testng-and-expectedexceptions-ive.html

    5 回复  |  直到 15 年前
        1
  •  35
  •   assylias    12 年前

    @Test(expectedExceptions) 适用于最常见的情况:

    • 您希望抛出一个特定的异常

    根据文件,如果没有,测试将失败 expectedException

    测试方法预期抛出的异常列表。如果没有抛出异常或与此列表中的异常不同,则此测试将被标记为失败。

    还不够:

    • 您的测试方法有几个语句,其中只有一个应该抛出

    在这种情况下,您应该恢复到传统(pre-TestNG)模式:

    try {
      // your statement expected to throw
      fail();
    }
    catch(<the expected exception>) {
      // pass
    }
    
        2
  •  11
  •   ThisaruG    7 年前

    使用 @Test 用于检查预期异常的批注。

    @Test(
        expectedExceptions = AnyClassThatExtendsException.class,
        expectedExceptionsMessageRegExp = "Exception message regexp"
    )
    

    或者,如果您不想检查异常消息,只需执行以下操作即可

    @Test(expectedExceptions = AnyClassThatExtendsException.class)
    

    这样,就不需要使用难看的try-catch块,只需在测试中调用异常抛出器方法。

        3
  •  2
  •   Steve Kuo    13 年前

    在我看来,最好用 Guard Assertions ,尤其是对于这样的测试(假设测试不是冗长复杂的,这本身就是一种反模式)。使用guard断言将强制您以以下任一方式设计SUT:

    但在我们考虑上述可能性之前,请再看一下以下片段:

    plane.bookAllSeats();
    plane.bookPlane(createValidItinerary(), null);
    

        4
  •  2
  •   Marwen Doukh creative_rd    7 年前

    如果您使用的是java7和testng,那么这可以用于java8,也可以使用lambda表达式

    class A implements ThrowingRunnable{
    
    
                @Override
                public void run() throws AuthenticationFailedException{
                    spy.processAuthenticationResponse(mockRequest, mockResponse, authenticationContext);
                }
            }
            assertThrows(AuthenticationFailedException.class,new A());
    
        5
  •  0
  •   Thomas Lötzer    15 年前

    为什么不使用链接到的博客文章中提到的try/fail/catch模式呢?

        6
  •  0
  •   rwitzel    14 年前

    catch-exception 可能提供了测试预期异常所需的所有内容。

        7
  •  0
  •   Java Impatient    6 年前

    like this :

    public class TestStackDataStructure {
        //All test methods use this variable.
        public Stack<String> stack;//This Stack class is NOT from Java.
    
        @BeforeMethod
        public void beforeMethod(){
        //Don't want to repeat this code inside each test, especially if we have several lines for setup.
            stack = new Stack<>(5);
        }
    
        @Test
        public void pushItemIntoAFullStack(){
            //I know this code won't throw exceptions, but what if we have some code that does ?
            IntStream.rangeClosed(1,5).mapToObj(i -> i + "").forEach(stack::push);
    
            try{
                stack.push("6");
                Assert.fail("Exception expected.");
            }catch (StackIsFullException ex) {
                // do nothing;
            }
        }
    
        //Other tests here.
    }
    

    或者,您可以根据建议更改api here :

    @Test
    public void pushItemIntoAFullStack(){
        IntStream.rangeClosed(1,5).mapToObj(i -> i + "").forEach(stack::push);
        Assert.assertFalse( stack.push("6"), "Expected push to fail." );
    }
    

    我更新了push方法,使其在操作通过或失败时返回true或false,而不是返回void。这个 Java Stack .push(item)返回您尝试插入的元素,而不是void。我不知道为什么。但是,它也从返回void的Vector继承了类似的方法addElement(item)。

    使push(item)返回布尔值或void的一个小缺点是,您被这些返回类型困住了。如果您返回Stack,那么您可以像这样方便地编写代码 stack.push(1).push(2).push(3).pop() . 但是,我不知道有多少人会经常这样写代码。

    Optional<T>

    @Test
    public void popEmptyStack(){
        Assert.assertTrue(stack.pop().isEmpty());
    }
    

    我想我现在摆脱了笨重的try-catch块和TestNg-expectedExceptions。希望我的设计现在很好。

    推荐文章