John Jiang

          a cup of Java, cheers!
          https://github.com/johnshajiang/blog

             :: 首頁 ::  :: 聯系 :: 聚合  :: 管理 ::
            131 隨筆 :: 1 文章 :: 530 評論 :: 0 Trackbacks
          <2011年12月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          留言簿(3)

          隨筆分類(415)

          隨筆檔案(130)

          文章分類

          Attach

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          探索JUnit4擴展:使用Rule
          在上一篇文章《探索JUnit4擴展:擴展Runner》中,討論了一種擴展JUnit4的方式,即,直接修改Test Runner的實現(BlockJUnit4ClassRunner)。但這種方法顯然不便于靈活地添加或刪除擴展功能。本文將使用JUnit4.7才開始引入的擴展方式--Rule來實現相同的擴展功能。(2010.12.25最后更新)

          1. Rule
          Rule是JUnit4.7才開始提供的一種擴展方式,它能夠替代大部分已有的Runner擴展。JUnit包含兩種Rule Annotation:@ClassRule與@Rule。@ClassRule應用于測試類中的靜態變量,而@Rule應用于成員變量;相同地是,這些變量必須是TestRule接口的實例,且訪問修飾符必須為public。
          上篇博文中,對BlockJUnit4ClassRunner進行了擴展,被擴展的方法是methodBlock,現在我們來看看該方法體中的代碼,
          protected Statement methodBlock(FrameworkMethod method) {
              Object test;
              
          try {
                  test
          = new ReflectiveCallable() {
                      @Override
                      
          protected Object runReflectiveCall() throws Throwable {
                          
          return createTest();
                      }
                  }.run();
              } 
          catch (Throwable e) {
                  
          return new Fail(e);
              }

              Statement statement
          = methodInvoker(method, test);
              statement
          = possiblyExpectingExceptions(method, test, statement);
              statement
          = withPotentialTimeout(method, test, statement);
              statement
          = withBefores(method, test, statement);
              statement
          = withAfters(method, test, statement);
              statement
          = withRules(method, test, statement);
              
          return statement;
          }
          但在BlockJUnit4ClassRunner中,possiblyExpectingExceptions(),withPotentialTimeout(),withBefores()和withAfters()都已經被標注為過時,JUnit建議使用Rule來替代這些方法的功能。

          2. TestLogRule
          如第1節所述,Rule Annotation要作用于TestRule接口的實例,那么就要先創建一個TestRule的實現類。
          public class TestLogRule implements TestRule {

              
          private static final DateFormat format = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss_SSS");

              @Override
              
          public Statement apply(Statement base, Description description) {
                  TestLogger testLogger 
          = description.getAnnotation(TestLogger.class);
                  
          if (testLogger != null) {
                      StringBuilder log 
          = new StringBuilder(format.format(new Date()));
                      log.append(
          " ").append(description.getClassName()).append("#")
                              .append(description.getMethodName()).append(
          "")
                              .append(testLogger.log());
                  System.out.println(log.toString());
              }

                  
          return base;
              }
          }
          如上所示,TestLogRule與上篇博文中的LoggedRunner的代碼有許多相同之處,功能則都是打印出指定的日志,每行日志又以當時的執行時間與完整方法名作為前綴。

          3. 使用Rule的CalculatorTest
          下面是新的測試類CalculatorTest,它將不使用BlockJUnit4ClassRunner的擴展LoggedRunner作為測試執行器,所以該類沒有使用@RunWith(LoggedRunner.class),那么在執行該測試類時仍然會使用BlockJUnit4ClassRunner。
          public class CalculatorTest {

              
          private static Calculator calculator = null;

              @Rule
              
          public TestLogRule testLogRule = new TestLogRule();

              @BeforeClass
              
          public static void createCalculator() {
                  calculator 
          = new Calculator();
              }

              @Test
              @TestLogger(log 
          = "a simple division")
              
          public void simpleDivide() {
                  
          int value = calculator.divide(82);
                  Assert.assertTrue(value 
          == 4);
              }

              @Test(expected 
          = ArithmeticException.class)
              @TestLogger(log 
          = "divided by zero, and an ArithmeticException thrown.")
              
          public void dividedByZero() {
                  calculator.divide(
          80);
              }
          }
          上篇博文中的CalculatorTest相比,本文中的CalculatorTest除了沒有使用LoggedRunner之外,還多了兩行代碼
          @Rule
          public TestLogRule testLogRule = new TestLogRule();
          在執行單元測試方法之前,BlockJUnit4ClassRunner會調用TestRule/TestLogRule中的apply()方法,即,會先打印出日志內容。

          4. 小結
          使用Rule對JUnit進行擴展,能夠避免對默認Runner的擴展,為測試類添加或移除Rule十分方便,而且Rule實現類本身也能很方便地被復用。在下一篇博文中將進一步探索Rule的應用。
          posted on 2011-12-24 23:26 John Jiang 閱讀(2346) 評論(0)  編輯  收藏 所屬分類: JavaUnitTestJUnit原創
          主站蜘蛛池模板: 石首市| 通州市| 兴国县| 石泉县| 措勤县| 西藏| 余江县| 错那县| 淮南市| 迁西县| 和平区| 邵东县| 商洛市| 巴楚县| 三江| 博爱县| 阳西县| 雷波县| 乐业县| 周至县| 德钦县| 星座| 威宁| 昭通市| 治县。| 永丰县| 娱乐| 三都| 新蔡县| 蛟河市| 昭苏县| 永丰县| 牟定县| 莱西市| 宜兰县| 平阳县| 昭通市| 吴堡县| 宁强县| 洛浦县| 宜兴市|