- 浏览: 2469484 次
- 性别:
- 来自: 杭州
文章分类
- 全部博客 (574)
- Book (62)
- Architecture (6)
- Java (39)
- Taobao (41)
- Distributed (4)
- Life (72)
- Database (7)
- Spring (16)
- Photography (15)
- Bicycle (41)
- Test (20)
- jBPM (8)
- Business (12)
- Movie (3)
- Ajax (15)
- Code (7)
- Eclipse (96)
- VIM (2)
- Music (6)
- Groovy (10)
- AutoHotKey (3)
- Dorado (10)
- Maven (7)
- Scrum (5)
- English (20)
- Financial (12)
- OSGi (3)
- Other (4)
- Tool (6)
- Browser (1)
- PPT (1)
- Project Management (4)
- Agile (6)
- Nosql (1)
- Search engine (6)
- Shell (2)
- Open Source (4)
- Storm (10)
- Guava (3)
- Baby (1)
- netty (1)
- Algorithm (1)
- Linux (1)
- Python (2)
最新评论
-
roy2011a:
https://github.com/ebottabi/sto ...
storm的序列化问题及与spring的结合方式 -
roy2011a:
能抗能打 写道哥们儿,你好!能共享下那个storm与sprin ...
storm的序列化问题及与spring的结合方式 -
Alick1:
兄弟,你之前是不是在深圳的正阳公司呆过啊?
storm的ack和fail -
liuleixwd:
先点个赞,写的非常好!有个问题请教下,如果我再bolt里不用e ...
storm的ack和fail -
yao-dd:
solr的facet查询
junit3和junit4是两个非常不同的版本, 不能简单的理解为是后者是前者的一个升级, 二者的内部实现有很大的不同。 这里只针对junit4以后的版本。
所有的testcase都是在Runner下执行的, 可以将Runner理解为junit运行的容器, 默认情况下junit会使用JUnit4ClassRunner作为所有testcase的执行容器。 如果要定制自己的junit, 则可以实现自己的Runner,最简单的办法就是Junit4ClassRunner继承, spring-test, unitils这些框架就是采用这样的做法。如在spring中是SpringJUnit4ClassRunner, 在unitils中是UnitilsJUnit4TestClassRunner, 一般我们的testcase都是在通过eclipse插件来执行的, eclipse的junit插件会在执行的时候会初始化指定的Runner。初始化的过程可以在ClassRequest中找到:
这里的局部变量fTestClass是当前的testcase类, 如果使用了注解, 它会从RunWith中拿到指定的Runner, 所以要定制的话, 最方便的做法就是通过@RunWith指定定制的Runner, Spring-test, Unitils都是这么干的^_^
下面来看JUnit4ClassRunner的构造器:
JUnit4ClassRunner没有默认的构造器, 从构造器中我们可以看出, 它需要一个参数, 这个参数就是我们当前要运行的testcase class, Runner拿到了要执行的testcase类之后, 就可以进一步拿到需要执行的测试方法, 这个是通过注解拿到的:
初始化完成之后, 就可以根据拿到的Runner, 调用其run方法,执行所有的测试方法了:
这里很多地方都利用了线程技术, 可以忽略不管, 最终都是要通过反射拿到需要执行的测试方法并调用, 最终的调用在MethodRoadie中:
下面是使用spring-test的runner如何来写testcase, 将会有不少简化(推荐懒人使用):
要测试的方法:
测试用例:
xml配置:
如果是使用maven的话, pom.xml的配置:
所有的testcase都是在Runner下执行的, 可以将Runner理解为junit运行的容器, 默认情况下junit会使用JUnit4ClassRunner作为所有testcase的执行容器。 如果要定制自己的junit, 则可以实现自己的Runner,最简单的办法就是Junit4ClassRunner继承, spring-test, unitils这些框架就是采用这样的做法。如在spring中是SpringJUnit4ClassRunner, 在unitils中是UnitilsJUnit4TestClassRunner, 一般我们的testcase都是在通过eclipse插件来执行的, eclipse的junit插件会在执行的时候会初始化指定的Runner。初始化的过程可以在ClassRequest中找到:
@Override public Runner getRunner() { return buildRunner(getRunnerClass(fTestClass)); } public Runner buildRunner(Class<? extends Runner> runnerClass) { try { return runnerClass.getConstructor(Class.class).newInstance(new Object[] { fTestClass }); } catch (NoSuchMethodException e) { String simpleName= runnerClass.getSimpleName(); InitializationError error= new InitializationError(String.format( CONSTRUCTOR_ERROR_FORMAT, simpleName, simpleName)); return Request.errorReport(fTestClass, error).getRunner(); } catch (Exception e) { return Request.errorReport(fTestClass, e).getRunner(); } } Class<? extends Runner> getRunnerClass(final Class<?> testClass) { if (testClass.getAnnotation(Ignore.class) != null) return new IgnoredClassRunner(testClass).getClass(); RunWith annotation= testClass.getAnnotation(RunWith.class); if (annotation != null) { return annotation.value(); } else if (hasSuiteMethod() && fCanUseSuiteMethod) { return AllTests.class; } else if (isPre4Test(testClass)) { return JUnit38ClassRunner.class; } else { return JUnit4ClassRunner.class; } }
这里的局部变量fTestClass是当前的testcase类, 如果使用了注解, 它会从RunWith中拿到指定的Runner, 所以要定制的话, 最方便的做法就是通过@RunWith指定定制的Runner, Spring-test, Unitils都是这么干的^_^
下面来看JUnit4ClassRunner的构造器:
public JUnit4ClassRunner(Class<?> klass) throws InitializationError { fTestClass= new TestClass(klass); fTestMethods= getTestMethods(); validate(); }
JUnit4ClassRunner没有默认的构造器, 从构造器中我们可以看出, 它需要一个参数, 这个参数就是我们当前要运行的testcase class, Runner拿到了要执行的testcase类之后, 就可以进一步拿到需要执行的测试方法, 这个是通过注解拿到的:
protected List<Method> getTestMethods() { return fTestClass.getTestMethods(); } List<Method> getTestMethods() { return getAnnotatedMethods(Test.class); } public List<Method> getAnnotatedMethods(Class<? extends Annotation> annotationClass) { List<Method> results= new ArrayList<Method>(); for (Class<?> eachClass : getSuperClasses(fClass)) { Method[] methods= eachClass.getDeclaredMethods(); for (Method eachMethod : methods) { Annotation annotation= eachMethod.getAnnotation(annotationClass); if (annotation != null && ! isShadowed(eachMethod, results)) results.add(eachMethod); } } if (runsTopToBottom(annotationClass)) Collections.reverse(results); return results; }
初始化完成之后, 就可以根据拿到的Runner, 调用其run方法,执行所有的测试方法了:
@Override public void run(final RunNotifier notifier) { new ClassRoadie(notifier, fTestClass, getDescription(), new Runnable() { public void run() { runMethods(notifier); } }).runProtected(); } protected void runMethods(final RunNotifier notifier) { for (Method method : fTestMethods) invokeTestMethod(method, notifier); } protected void invokeTestMethod(Method method, RunNotifier notifier) { Description description= methodDescription(method); Object test; try { test= createTest(); } catch (InvocationTargetException e) { notifier.testAborted(description, e.getCause()); return; } catch (Exception e) { notifier.testAborted(description, e); return; } TestMethod testMethod= wrapMethod(method); new MethodRoadie(test, testMethod, notifier, description).run(); }
这里很多地方都利用了线程技术, 可以忽略不管, 最终都是要通过反射拿到需要执行的测试方法并调用, 最终的调用在MethodRoadie中:
public void run() { if (fTestMethod.isIgnored()) { fNotifier.fireTestIgnored(fDescription); return; } fNotifier.fireTestStarted(fDescription); try { long timeout= fTestMethod.getTimeout(); if (timeout > 0) runWithTimeout(timeout); else runTest(); } finally { fNotifier.fireTestFinished(fDescription); } } public void runTest() { runBeforesThenTestThenAfters(new Runnable() { public void run() { runTestMethod(); } }); } public void runBeforesThenTestThenAfters(Runnable test) { try { runBefores(); test.run(); } catch (FailedBefore e) { } catch (Exception e) { throw new RuntimeException("test should never throw an exception to this level"); } finally { runAfters(); } } protected void runTestMethod() { try { fTestMethod.invoke(fTest); if (fTestMethod.expectsException()) addFailure(new AssertionError("Expected exception: " + fTestMethod.getExpectedException().getName())); } catch (InvocationTargetException e) { Throwable actual= e.getTargetException(); if (actual instanceof AssumptionViolatedException) return; else if (!fTestMethod.expectsException()) addFailure(actual); else if (fTestMethod.isUnexpected(actual)) { String message= "Unexpected exception, expected<" + fTestMethod.getExpectedException().getName() + "> but was<" + actual.getClass().getName() + ">"; addFailure(new Exception(message, actual)); } } catch (Throwable e) { addFailure(e); } }
下面是使用spring-test的runner如何来写testcase, 将会有不少简化(推荐懒人使用):
要测试的方法:
public class ExampleObject { public boolean getSomethingTrue() { return true; } public boolean getSomethingFalse() { return false; } }
测试用例:
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:/applicationContext.xml" }) public class ExampleTest { @Autowired ExampleObject objectUnderTest; @Test public void testSomethingTrue() { Assert.assertNotNull(objectUnderTest); Assert.assertTrue(objectUnderTest.getSomethingTrue()); } @Test @Ignore public void testSomethingElse() { Assert.assertNotNull(objectUnderTest); Assert.assertTrue(objectUnderTest.getSomethingFalse()); } }
xml配置:
<?xml version="1.0" encoding="gb2312"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="objectUnderTest" class="com.taobao.demo.spring.test.ExampleObject"> </bean> </beans>
如果是使用maven的话, pom.xml的配置:
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>2.5.5</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>2.5.4</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>2.5.4</version> </dependency> </dependencies>
评论
2 楼
skyuck
2011-03-25
学习了,楼主整理的很好
1 楼
xly_971223
2009-04-23
楼主整理的非常好
只是版本太老了
junit4.6已经废弃了JUnit4ClassRunner类
好多的方法名字都变了
只是版本太老了
junit4.6已经废弃了JUnit4ClassRunner类
好多的方法名字都变了
发表评论
-
Effective Unit Test:代码面前并非人人平等
2012-02-05 15:38 1702这里的观点非常值得探讨, 所有的产品代码就像是一项投资, 有些 ... -
使用Guava Supplier Mock Datetime
2012-02-04 23:35 2801通过下面的例子了解Guava Supplier的用法.在做单元 ... -
对多线程进行测试
2011-07-02 15:31 1413在junit下, 很难对多线程的代码进行测试, 因此需要借助其 ... -
补习一下EasyMock
2010-04-28 09:18 5046最近有时间, 再温习一下easymock相关的东东 http ... -
结合使用Dummy, InjectTo, PartialMock的单元测试
2009-12-24 21:21 1481结合使用Dummy, InjectTo, PartialMoc ... -
使用代码方式运行指定单元测试类及方法
2009-12-17 08:57 1767记一下, 备忘 private void runT ... -
JunitCore
2009-12-15 01:03 0JUnitCore core = new JUnitCore( ... -
修改dbunit的几个bug兼对dbunit进行扩展
2009-12-08 20:51 3193最近在对unitils进行扩展, 主要是数据库这块儿的内容, ... -
让Unitils实现excel下的多数据源支持
2009-12-03 21:02 3944说明:这里的多数据源需要利用spring中配置的多个DataS ... -
unitils中spring module初始化源码解读
2009-12-03 20:32 2655spring module的初始化还算简单, 但是熟悉里面的原 ... -
解决unitils中的dbunit使用spring中定义的多数据源
2009-12-02 20:07 3172最近在研究unitils, dbunit来适应目前的单元测试. ... -
Unitils 学习笔记
2009-11-27 19:44 7789源码部分 EasyMock相关的 有三个注解: Mock ... -
使用classloader自定义测试套件TestSuite
2009-10-21 19:04 2341junit自带了一个suite用来将多个test case放在 ... -
《单元测试之道Java版——使用JUnit》读书笔记
2009-06-09 23:06 3419这个可能是到目前为止 ... -
JunitRunner定制之模仿@Before对属性进行初始化
2009-02-12 21:54 2542在测试的过程中, 会用到一些模拟数据, 希望在每次调用测试方法 ... -
打造自己的单元测试容器——Junit Runner扩展举例
2009-02-05 23:40 6217最近对java的annotation和junit的Runner ... -
最近单元测试中写的一个Assert
2009-01-15 22:03 2916该类提供的assert方法主要针对数据库的单元测试中, 使用S ... -
用于生成mock模型对象Setter代码工具类
2009-01-12 10:35 1800最近写的一个工具类, 用来生成mock的javabean对象, ... -
EasyMock最佳实践
2008-12-20 20:43 30115推荐easymock入门贴: 窥探 ... -
JUnit 4新特性笔记
2008-12-11 08:47 2928测试任何可能的错误。 ...
相关推荐
JUnit4源码的完整版本包含了整个框架的实现细节,对于理解其工作原理、学习测试驱动开发(TDD)以及进行自定义扩展非常有帮助。 1. **JUnit核心概念**: - **Test Case**:在JUnit4中,测试用例是通过继承`org....
junit 的源码jar包 junit 的源码jar包 junit 的源码jar包
【标题】"junit4 单元测试源码"涉及的是Java编程中单元测试的重要工具JUnit4的使用,这是对代码进行验证和调试的关键部分。JUnit4是JUnit框架的一个版本,它提供了更灵活的注解、测试套件管理和断言方式,使得编写...
JUnit4.8.1源码包 版本4.8.1 只有源码。
这个"junit4测试源码"可能包含了JUnit4框架的源代码,使得用户能够深入理解其内部工作原理,便于自定义扩展或学习测试驱动开发(TDD)的最佳实践。 首先,JUnit4引入了注解(Annotation)的概念,使得测试类和测试...
《Junit Recipes 源码》是一份宝贵的资源,它包含了一系列与单元测试相关的实践案例,主要用于学习和应用JUnit测试框架。JUnit是Java编程语言中最常用的单元测试工具,它为开发者提供了一种简单且强大的方式来编写可...
JUnit4是Java编程语言中最广泛使用的单元测试框架之一,它为开发者提供了编写和运行可重复、可靠的测试用例的工具。这个压缩包包含了两个重要的文件:`junit-4.11.jar` 和 `junit-4.11-sources.jar`。 `junit-4.11....
JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。 [1] JUnit是由 Erich Gamma 和 Kent Beck 编写的一个回归测试框架(regression testing framework)。Junit测试是...
这个"junit4测试源码 免费"的资源包含的是JUnit4框架的源代码,这对于理解其内部工作原理、学习如何编写更高效、更健壮的测试用例以及进行自定义扩展具有极大的价值。 JUnit4引入了许多新特性,极大地提高了测试的...
junit4.12源码,便于查看源码,重写方法,为己所用。
7. **测试规则**:JUnit4中的TestRule接口和JUnit5中的Extension API提供了扩展测试行为的能力,如日志记录、性能测试等。通过源码,我们可以学习如何自定义测试规则。 8. **异步测试**:随着并发编程的普及,JUnit...
本教程将深入讲解JUnit4的使用方法,并附带源码供学习者实践和参考。 一、JUnit4概述 JUnit4是JUnit系列的第四个主要版本,它引入了许多新特性,如注解(Annotations)、参数化测试、测试套件的改进以及更加灵活的...
JUnit4是Java编程语言中最广泛使用的单元测试框架之一,它为开发者提供了一种方便、高效的方式来验证代码的正确性。这个“junit4 jar完整包”包含了所有你需要进行单元测试的类和接口,使得测试过程变得简单且易于...
JUnit4测试框架是Java开发中广泛使用的单元测试工具,它为开发者提供了编写和运行可重复、可靠的测试用例的能力。这个“junit4测试jar包”包含了一切你需要在项目中集成JUnit4进行测试的库文件。只需将其复制到你的...
### JUnit源码及其涉及的设计模式 #### 一、引言 JUnit作为一款广泛应用于Java项目的单元测试框架,其设计理念和实现方式对于软件开发者来说具有很高的学习价值。本文将深入探讨JUnit源码,并重点关注其中使用的...
本资料包"junit4测试数据库源码"主要涵盖了Junit4的新特性assertThat断言以及如何利用Junit4进行MySQL和Oracle两种主流数据库的增删改查操作的测试。 首先,我们来了解一下Junit4的assertThat断言。在旧版本的Junit...
JUnit4是Java编程语言中最广泛使用的单元测试框架之一,它为开发者提供了编写可重复执行、易于维护的测试代码的能力。这个“junit4 jar包”包含了运行JUnit4测试所必需的库文件,主要包括两个核心组件:`junit-4.11....
**Junit源码分析(圣思园)** Junit是Java编程语言中最广泛使用的单元测试框架,它使得开发者能够方便地编写和运行可重复的、可靠的测试用例。本篇文章将深入探讨Junit的源码,揭示其内部工作原理,帮助我们更好地...
### JUnit4 学习知识点详解 #### 一、JUnit4 概述 JUnit4 是 JUnit 测试框架的一个重大更新版本,它充分利用了 Java 5 的注解(Annotation)特性来简化测试用例的编写过程。注解是一种元数据,用于描述程序中的...
**JUnit4教程——初探单元测试的艺术** JUnit4是Java编程语言中广泛使用的单元测试框架,它是Java开发者进行软件质量保证的重要工具。本教程将深入浅出地介绍JUnit4的基本概念、核心特性以及如何在实际项目中应用它...