`
longgangbai
  • 浏览: 7330691 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

[转]探索JUnit4扩展:深入Rule

阅读更多
转载自:
探索JUnit4扩展:深入Rule

本文是"探索JUnit4扩展"系列中的第三篇,将进一步探究Rule的应用,展示如何使用Rule来替代@BeforeClass,@AfterClass,@Before和@After的功能。(2012.01.04最后更新)

在本系列的第二篇《探索JUnit4扩展:应用Rule》中提到,可以使用Rule替代现有的大部分Runner扩展,而且也不提倡对Runner中的withBefores(),withAfters()等方法进行扩展。本文将介绍如何使用Rule去实现@Before,@After和@BeforeClass的相同功能。

1. BaseRule
    首先要创建一个较通用的TestRule实现BaseRule,它会释放出两个扩展点,一个在执行测试方法之前,before();另一个在执行测试方法之后after()。下面是该类的代码,

public abstract class BaseRule implements TestRule {

    @Override
    
public Statement apply(Statement base, Description description) {
        
return new RuleStatement(base, description);
    }

    
private class RuleStatement extends Statement {

        
private Statement base = null;

        
private Description description = null;

        
private RuleStatement(Statement base, Description description) {
            
this.base = base;
            
this.description = description;
        }

        @Override
        
public void evaluate() throws Throwable {
            before(base, description);
            
try {
                base.evaluate();
            } 
finally {
                after(base, description);
            }
        }
    }

    
protected void before(Statement base, Description description) throws Throwable {

    }

    
protected void after(Statement base, Description description) {

    }
}

如果对JUnit4的源代码略有认知,可能会发现BaseRule与JUnit4提供的TestRule实现ExternalResource代码相似。关键的不同之处是,BaseRule中的before()与after()方法都提供了Statement与Description类型的参数,这使得它能够完成更复杂的工作。

2. CalculatorTest
    本文使用的CalculatorTest将不使用@BeforeClass,@Before和@After,而会创建两个BaseRule的实例:一个用于替代@BeforeClass和@AfterClass(本系列目前还未使用过@AfterClass),另一个则替代@Before和@After。

public class CalculatorTest {

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

    
private static Calculator calculator = null;

    @ClassRule
    
public static BaseRule classRule = new BaseRule() {

        
protected void before(Statement base, Description description) throws Throwable {
            calculator 
= new Calculator();
        };
    };

    @Rule
    
public BaseRule rule = new BaseRule() {

        
protected void before(Statement base, Description description) throws Throwable {
            printBeforeLog(description);
        };

        
protected void after(Statement base, Description description) {
            printAfterLog(description);
        };

        
private void printBeforeLog(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());
            }
        }

        
private void printAfterLog(Description description) {
            StringBuilder log 
= new StringBuilder(format.format(new Date()));
            log.append(
" ").append(description.getClassName()).append("#")
                    .append(description.getMethodName()).append(
" end");
            System.out.println(log.toString());
        }
    };

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

值得注意的是,classRule是静态变量,它使用@ClassRule Annotation,将替代@BeforeClass和@AfterClass;而rule是成员变量,它使用@Rule Annotation,将替代@Before和@After。与之前文章不同的是,此处不仅会在执行测试方法之前打印指定内容的日志(printBeforeLog()),还会在执行测试方法之后打印一条固定格式的日志(printAfterLog()),用于指示该测试方法已经执行完毕了。

3. 小结
    使用Rule可以替代绝大部分的Runner扩展,而且特定的Rule实现可以被复用,也易于添加或移除Rule实例,这些都大大地提高了灵活性。值得注意地是,本文虽然使用Rule代替了@BeforeClass,@AfterClass,@Before和@After的功能,但并不意味着就应当这么做。就我个人所想,将传统的Fixture功能交由@BeforeClass,@AfterClass,@Before和@After实现,仍然是一种不错的选择。

分享到:
评论

相关推荐

    探索JUnit4扩展:深入Rule

    《探索JUnit4扩展:深入Rule》 JUnit是Java开发者最常用的单元测试框架,它极大地简化了测试代码的编写。在JUnit4中,引入了一个强大的特性——Rule,这使得测试更加灵活且可定制化。本文将深入探讨Rule的概念、...

    探索JUnit4扩展:使用Rule

    标题“探索JUnit4扩展:使用Rule”涉及到的是Java单元测试框架JUnit的一个高级特性,即`@Rule`。在Java开发中,单元测试是确保代码质量、可维护性和可靠性的重要手段,而JUnit作为最流行的Java单元测试框架之一,...

    junit4入门

    《Junit4 入门详解》 JUnit 是一个用于Java编程语言的单元测试框架,而Junit4作为其第四代版本,引入了许多新特性和改进,使得测试...同时,不断探索Junit4的高级特性,你会发现它能为你的软件开发带来无尽的便利。

    [原]深入JUnit4.x

    【深入JUnit4.x】—— 探索Java单元测试框架的核心 JUnit是Java开发中最常用的单元测试框架,尤其在JUnit4.x版本中,它引入了许多改进和特性,使得测试更加灵活和强大。这篇深入的文章将围绕JUnit4.x的核心概念、...

    junit4-example:看junit4源码-看

    《深入解析JUnit4:探索开源测试框架的精髓》 JUnit4是Java开发中广泛使用的单元测试框架,它的开源性质使得开发者能够深入理解其内部机制,从而更好地利用它进行测试驱动开发(TDD)。本篇文章将从`junit4-example...

    junit深入

    《Junit 深入探索:源码剖析与测试工具运用》 Junit,作为Java领域最常用的单元测试框架,是每一个开发者必备的技能之一。本文将深入探讨Junit的内在机制,通过源码分析以及实际应用示例,帮助读者更全面地理解和...

    junit-master.zip

    《深入理解JUnit:Java单元测试框架的探索与实践》 JUnit是Java编程语言中最流行的单元测试框架之一,它为开发者提供了简洁、高效的测试工具,帮助确保代码的质量和可靠性。本篇文章将围绕“junit-master.zip”这个...

    junit4.10.zip

    通过分析这个压缩包,我们可以深入理解JUnit的工作原理,以及如何在实际开发中有效地进行单元测试。 JUnit 4.10是一个重要的里程碑,因为它引入了一些关键的改进和特性。首先,让我们看看其核心概念: 1. **测试...

    JUnit

    JUnit 5引入了扩展机制,允许更深入地定制测试行为。 **8. 编写测试** 编写有效的JUnit测试需要遵循一些最佳实践,如保持测试方法独立,避免副作用,以及使用适当的断言。 **9. 测试套件与分类** 通过`@Suite`注解...

    junit学习资料

    8. **测试规则**:JUnit的`TestRule`接口允许定义自定义的测试规则,例如,可以使用`@Rule`注解来实现测试方法执行前后的额外操作,如资源清理或日志记录。 9. **定时器与超时**:`@Test(timeout = 1000)`可以设定...

    Drools 10分钟入门 代码 PPT

    6. **规则流(Drools Flow)**:如果你深入学习,可能会涉及到Drools Flow,它扩展了Drools,支持工作流程和业务流程的管理。 通过这个入门教程,你将能理解Drools的基本工作原理,学会编写简单的规则,并在Java...

Global site tag (gtag.js) - Google Analytics