2010-04-14 47 views
124

我发现JUnit的正确使用(或至少文档)非常混乱。 这个问题既可以作为未来的参考,也可以作为一个真正的问题。JUnit混淆:使用'扩展TestCase'或'@Test'?

如果我理解正确的话,有创建和运行JUnit测试方法主要有两种:

方法A(JUnit的3式):创建一个扩展的TestCase类,并开始测试方法用词test。将该类作为JUnit Test(在Eclipse中)运行时,将自动运行以test这个词开头的所有方法。

import junit.framework.TestCase; 

public class DummyTestA extends TestCase { 

    public void testSum() { 
     int a = 5; 
     int b = 10; 
     int result = a + b; 
     assertEquals(15, result); 
    } 
} 

方法B(JUnit 4中样式):创建一个 '正常' 的类和在前面加上一个@Test注释的方法。请注意,您不必使用单词test开始该方法。

import org.junit.*; 
import static org.junit.Assert.*; 

public class DummyTestB { 

    @Test 
    public void Sum() { 
     int a = 5; 
     int b = 10; 
     int result = a + b; 
     assertEquals(15, result); 
    } 
} 

将两者混合似乎并不是一个好主意, this stackoverflow question

现在,我的问题(S):

  1. 什么是首选的方法,或当您将使用一个,而不是其他?
  2. 方法B允许通过扩展@Test注释来测试异常,如@Test(expected = ArithmeticException.class)但是,如何使用方法A测试异常?
  3. 当使用方法A,就可以组中的测试套件这样一些测试类:

    TestSuite suite = new TestSuite("All tests");
    suite.addTestSuite(DummyTestA.class);
    suite.addTestSuite(DummyTestAbis.class);

    但这不能与方法B中使用(因为每个测试类都应该子类TestCase)。 对方法B进行分组测试的正确方法是什么?

编辑:我已经添加了JUnit版本,这两种方法

回答

96

的区别是相当容易:

  • 延伸TestCase是(当然它仍然支持JUnit 4)
  • 使用@Test注释是由JUnit 4引入的方式

通常,您应该选择注释路径,除非需要与JUnit 3(和/或早于Java 5的Java版本)的兼容性。新办法有几个好处:

要在一个JUnit 3 TestCase测试预期的例外

  • 支持替代测试运行,你就必须使文字清晰。

    public void testMyException() { 
        try { 
        objectUnderTest.myMethod(EVIL_ARGUMENT); 
        fail("myMethod did not throw an Exception!"); 
        } catch (MyException e) { 
        // ok! 
        // check for properties of exception here, if desired 
        } 
    } 
    
  • +0

    有帮助和全面的答案,但我不完全理解“检查异常消息”。检查硬编码的字符串将成为维护的噩梦。您必须具有“检查特定异常类型的属性”的含义。 – thSoft 2010-04-14 09:17:29

    +3

    @thSoft:它并不经常被使用,但偶尔我想确保例外方法提到违规字段。然后,一个简单的'assertTrue(e.getMessage()。contains(“foo”))'可能会有用。 – 2010-04-14 09:22:06

    +1

    即使在JUnit4中,当你必须检查消息或异常的其他属性(如原因)时,这也是一个重要的习惯用法。预期的方法只检查类型。 – Yishai 2010-04-14 13:35:22

    21

    我有JUnit 4中(译注方法)的偏爱,因为我觉得它更灵活。

    如果你想建立测试套件JUnit 4中,你必须创建一个类分组这样所有的测试:

    import org.junit.runner.RunWith; 
    import org.junit.runners.Suite; 
    import org.junit.runners.Suite.SuiteClasses; 
    
    
    @RunWith(Suite.class) 
    @SuiteClasses({ 
        Test1.class, 
        Test2.class, 
        Test3.class, 
        Test4.class 
    })public class TestSuite 
    { 
    /* empty class */ 
    } 
    
    1
    1. “首选”的方法是使用已经出台的注解,因为JUnit 4中他们做了很多事情变得更加容易(见你的第二个问题)

    2. 可以使用对于简单的try/catch块:

    
    public void testForException() { 
        try { 
         Integer.parseInt("just a string"); 
         fail("Exception should have been thrown"); 
        } catch (final Exception e) { 
         // expected 
        } 
    } 
    
    3

    你应该使用JUnit 4,这是更好。

    许多框架已经开始废弃JUnit 3.8支持。

    这是从Spring 3.0参考文档:

    【警告】传统的JUnit 3.8类 层次弃用

    在一般情况下,你应该尽量使用最新的稳定版本一个框架,当你开始新的东西。

    14

    您的问题有一个未答复的部分,那就是“对方法B进行分组测试的正确方法是什么?”

    官方答案是你用@RunWith(Suite)注解一个类。类),然后使用@ Suite.SuiteClasses注释来列出这些类。这是JUnit开发人员如何做的(手动列出套件中的每个类)。在许多方面,这种方法是一种改进,因为在套件和套件行为之前添加是微不足道和直观的(只需将@BeforeClass和@AfterClass方法添加到使用@RunWith注释的类中 - 比旧的TestFixture好得多)。

    但是,它有一个倒退,因为注释不允许您动态创建类的列表,并且解决该问题会变得有点难看。您必须继承Suite类的子类,并在子类中动态创建类的数组并将其传递给Suite构造函数,但这是一个不完整的解决方案,因为Suite的其他子类(例如Categories)不能使用它,不支持动态测试类集合。

    +1

    +1。在着手编写动态解决方案以将测试添加到TestSuite之后,我必须在每个测试中扩展TestCase。这反过来打破了以前的工作单元测试,它使用JUnit4注释来定义预期的异常。我在寻找一种动态填充测试套件的方式,让我有了这个线索,特别是您的答案,我相信这是继续使用JUnit 3的少数理想的理由之一。 – 8bitjunkie 2011-06-24 16:58:41