2012-04-13 91 views
2

我想知道是否可以测试(使用JUnit)由异常生成的特定消息被抛出而不仅仅是“是否抛出异常”。 例如,JunitTest.java代码实际上会通过测试,因为抛出了异常,但是如果我还想测试由异常生成的字符串等于:“测试异常:整数可能不是负数..”这可能吗?JUnit:测试某种类型的异常

TestException.java

public class TestException extends Exception { 
    /** 
    * @param message informative message about the problem found 
    */ 
    public TestException (String message) { 
     super("Test Exception: " + message); 
    } 
} 

Test.java

public void function(Integer mustBePositive) throws TestException { 
    if (mustBePositive < 0) { 
     throw new TestException("Integer may not be negative.."); 
    } 
    else { 
     mustBePositive = myNum 
    } 
} 

JunitTest.java

import org.junit.*; 

public class JUnitTest { 

    @Test(expected = TestException.class) 
    public void functionTest() throws TestException { 
     function(-1); 
    } 
} 
+0

的[?在Java中我怎么能验证使用JUnit抛出的异常]可能重复(http://stackoverflow.com/questions/785618/in- java-how-can-i-validate-a-thrown-exception-with-junit) – artbristol 2012-04-13 12:14:44

+0

@artbristol答案似乎是使用老版本的JUnit(不需要'expected = ...'注解)。 – assylias 2012-04-13 12:18:52

回答

2
assertEquals("Test Exception: Integer may not be negative..", e.getMessage()); 
7

注:我认为@Matthew's answer是优越的。

您可以使用以下结构 - 它测试是否引发了正确的异常(TestException.class该消息符合预期。

@Test(expected = TestException.class) 
public void test_function_negative() { 
    try { 
     function(-5); 
    } catch (TestException ex) { 
     assertEquals("Integer may not be negative..", ex.getMessage()); 
     throw ex; 
    } 
} 

编辑
为什么我重新抛出异常(评论如下):下面的第一个测试通过,而第二个则没有。所以它增加了一个额外的验证层。现在,如果我在下面的代码中捕获了ExceptionB,那么这两个测试都会失败。

@Test 
public void test1() throws ExceptionB { 
    try { 
     throw new ExceptionA(); 
    } catch (ExceptionA e) { 
     assertEquals("message", e.getMessage()); 
    } 
} 

@Test(expected=ExceptionB.class) 
public void test2() throws ExceptionA { 
    try { 
     throw new ExceptionA(); 
    } catch (ExceptionA e) { 
     assertEquals("message", e.getMessage()); 
     throw e; 
    } 
} 

public class ExceptionA extends Exception{ 
    @Override 
    public String getMessage() { 
     return "message"; 
    } 
} 
public class ExceptionB extends ExceptionA{} 
+0

Thankyou这正是我之后:) – Samwisest 2012-04-13 12:21:08

+0

在这种情况下应该assertTrue。 – 2012-04-13 12:23:14

+0

它正在工作,但我已经修改为您的版本,这是更好的。 – assylias 2012-04-13 12:24:56

1

我做这种方式:

@Test 
    public void functionTest() throws TestException { 
    try { 
     function(-1); 
     fail("This should have thrown an exception."); 
    } catch (TextException e) { 
     assertEquals("exception test produced an unexpected message", EXPECTED_TEXT, e.getMessage()); 
    } 
    } 

这可能不是优雅,但它很容易理解,涵盖所有的基础。免责声明 - 我没有编译它。

-1

import org.junit。 *;

公共类JUnitTest {

@Test 
public void functionTest() throws TestException { 
    try { 
     function (-1); 
     fail(""); 
    } catch (TestException e) { 
     if (!e.getMessage().equals("Integer may not be negative..")) 
      fail(""); 
    } 
} 
+0

如果你打算这样做,你应该使用assertEquals或assertThat。如果这个测试失败了,为什么 – tddmonkey 2012-04-13 12:16:22

1

其他人已经指出的结构,你可以用它来测试这一点,但我本身不会测试消息这可能是非常脆。

您应该创建一个自定义异常,获取所有需要的数据并声明数据在那里。如果你真的关心这个消息,那么你可以单独对异常本身进行单元测试。

鉴于你例如:

public void function(Integer mustBePositive) throws TestException { 
    if (mustBePositive < 0) { 
     throw new TestException("Integer may not be negative.."); 
    } 
    else { 
     mustBePositive = myNum 
    } 

你可以随便扔一个NegativeNumberException。如果你真的想知道电话号码是什么,你可以修改你的代码把这个当作参数:

public void function(Integer mustBePositive) throws TestException { 
    if (mustBePositive < 0) { 
     throw new NegativeNumberException(mustBePositive); 
    } 
    else { 
     mustBePositive = myNum 
    } 

然后在您的测试:

@Test(expected = NegativeNumberException.class) 
public void functionTest() throws TestException { 
    try { 
     function(-1); 
    } catch (NegativeNumberException nne) { 
     assertThat(nne.getNumber(), equalTo(-1)); 
    } 
} 

你例外,现在却生成消息它看起来合适,并且对该输出的更改不会影响您的其他测试代码

+0

没有输出如果字符串很重要,我会测试它。除非字符串是动态的,否则我不会认为这样的测试比任何其他测试更脆弱。无论如何,该字符串应该是TestJava中的一个公共常量。然后测试(和实际的代码)可以引用常量。 – 2012-04-13 13:57:05

+1

如果字符串足够重要以便测试,那么将其作为测试代码和生产代码引用的常量会导致无意义的测试。然后你所测试的是他们引用相同的字符串,但没有任何内容来验证实际的字符串是否正确 – tddmonkey 2012-04-20 14:49:47

6

您可以使用标准JUnit TestRuleExpectedException。这允许您测试引发异常,并测试异常附带的消息。例如:

public static class HasExpectedException { 
    @Rule 
    public ExpectedException thrown= ExpectedException.none(); 

    @Test 
    public void throwsNothing() { 
    // no exception expected, none thrown: passes. 
    } 

    @Test 
    public void throwsNullPointerException() { 
    thrown.expect(NullPointerException.class); 
    throw new NullPointerException(); 
    } 

    @Test 
    public void throwsNullPointerExceptionWithMessage() { 
    thrown.expect(NullPointerException.class); 
    thrown.expectMessage("happened?"); 
    thrown.expectMessage(startsWith("What")); 
    throw new NullPointerException("What happened?"); 
    } 
} 

expectMessage()它可以是一个字符串(该消息的一个子)或匹配器,所以你可以做正则表达式检查或什么的。

1

catch-exception由支持这样的场景:

import static com.googlecode.catchexception.CatchException.*; 

public void testFunction() throws Exception { 
    verifyException(obj).function(-1); 
    assertEquals("Integer may not be negative..", 
       caughtException().getMessage()); 
}