首页 > 代码库 > 单元测试——junit
单元测试——junit
一、前言
JUnit4对于JUnit3来说是一个历史性的改革。因为JUnit4引入了注解(annotation),通过解析注解就可以为测试提供相应的信息,抛弃JUnit3使用命名约束以及反射机制的方法。但是JUnit4.x与JUnit3.8向后是兼容的。
官网:http://junit.org/junit4/
预备知识点:
源文件夹:在eclipse中在项目中,右键新建选项中有一个源文件夹(Source folder)。其与普通文件夹的不同点表现在,他的图标是十字型的包裹图案。
源文件夹的特点:在源文件夹中的文件会自动转换为class文件存在于当前项目的bin目录中。
在eclipse中可以在需要测试的类文件上右击->新建->JUnit测试用例->创建测试用例(可以选择版本,文件夹路径,以及生成的其它细节)
计算机并不能准确地表示所有的浮点数,通常都会有一些偏差。因此如果用断言来比较浮点数,则需要制定一个额外的误差参数(tolerance)。
建议:
- 不建议使用eclipse集成的JUnit,因为其版本是固定的,相对而言可能一些新特性是不支持的。
- 测试代码放在与src同级的另外一个源文件夹中
- 测试文件的路径结构应与被测试的源文件相同
- 测试文件的命名:Test+源文件名称
junit3和junit4的使用区别:
- 在JUnit3中需要继承TestCase类,但在JUnit4中已经不需要继承TestCase
- 在JUnit3中需要覆盖TestCase中的setUp和tearDown方法,其中setUp方法会在测试执行前被调用以完成初始化工作,而tearDown方法则在结束测试结果时被调用,用于释放测试使用中的资源,而在JUnit4中,只需要在方法前加上@Before,@After
- 在JUnit3中对某个方法进行测试时,测试方法的命令是固定的,例如对addBook这个方法进行测试,需要编写名字为testAddBook的测试方法,而在JUnit4中没有方法命令的约束,在方法的前面加上@Test,这就代表这个方法是测试用例中的测试方法
- 新的断言assertThat
- @BeforeClass 和 @AfterClass 。在JUnit3,如果所有的test case仅调用一次setUp()和tearDown()需要使用TestSetup类
- 测试异常处理@Test(expected = DataFormatException.class)
- 设置超时@Test(timeout = 1000)
- 忽略测试@Ignore
- 集成测试
如何尽量提高测试代码的兼容性:
- JUnit4中初始化函数命名为setUp(),释放资源的函数命名为tearDown()
- JUnit4中测试函数一test
- 为了在JUnit4中像JUnit3中直接使用assert(断言),我们要静态导入Assert类(import static org.junit.Assert.*;)
测试代码需要做的事情:
- 准备测试所需要的各种条件(创建所有必须的对象,分配必要的资源等等)
- 调用要测试的方法
- 验证被测试方法的行为和期望是否一致
- 完成后清理各种资源
二、JUnit3使用
推荐图书:《单元测试之道Java版:使用JUnit》
随书代码:http://download.csdn.net/detail/fanxiaobin577328725/9632002
JUnit3采用的是反射机制,所以对名字的命名非常重要。
1.测试方法必须在原方法的方法首部添加Test,测试类没有这样强制要求。
2.测试类必须继承TestCase。
3.测试方法覆盖setUp和tearDown方法来初始化和释放资源。(测试每一个方法都会执行一次setUp和tearDown方法)
OneTimeSetUp是什么?没关系向下看就可以了,下面将给出详细解释。
断言方法:(因为继承了TestCase,而TestCase继承了Assert类,所以直接使用断言)
基本上:下列函数的第一个参数可以是可选的信息参数。
常用方法 | 解释 |
---|---|
assertArrayEquals(expecteds, actuals) | 查看两个数组是否相等 |
assertEquals(expected, actual) | 查看两个对象是否相等,类似于字符串比较使用的equals()方法 |
assertEquals(String message,expected, actual) | 与上面一样,就是在出错时显示message信息。 |
assertNotEquals(first, second) | 查看两个对象是否不相等。 |
assertNull(object) | 查看对象是否为空 |
assertNotNull(object) | 查看对象是否不为空 |
assertSame(expected, actual) | 查看两个对象的引用是否相等。类似于使用“==”比较两个对象 |
assertNotSame(unexpected, actual) | 查看两个对象的引用是否不相等。类似于使用“!=”比较两个对象 |
assertTrue(condition) | 查看运行结果是否为true |
assertFalse(condition) | 查看运行结果是否为false |
assertThat(actual, matcher) | 查看实际值是否满足指定的条件 |
fail() | 让测试失败 |
默认情况下,JUnit会自动运行所有的test...方法。然而任何测试类都能包含一个名为suite的静态方法:
public static Test suite() { TestSuite suite = new TestSuite(); //想要测试的代码 <pre name="code" class="java"> //.......
return suite; }suite方法不仅可以调用当前测试类中的指定测试函数,还可以调用其他测试类以及其他测试类中的suite方法。
示例:
/** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * A brute-force solution to the Travelling Salesman Problem. * * It will run in exponential time. * * Better solutions use genetic algorithms and such. */ public class TSP { /** * For the top numCities in our territory, compute the shortest path * and return thr total number of miles in that path. */ public int shortestPath(int numCities) { // Ha! Mock object! switch (numCities) { case 50: return 2300; case 5: return 140; case 10: return 586; } return 0; } /** * Load the cities for the given territory and lock them */ public void loadCities(String name) { } /** * Relase the lock on cities in this territory */ public void releaseCities() { } }测试代码:(TestClassTwo)
/** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ import junit.framework.*; public class TestClassTwo extends TestCase { public TestClassTwo(String method) { super(method); } // This one takes a few hours... public void testLongRunner() { TSP tsp = new TSP(); // Load with default cities assertEquals(2300, tsp.shortestPath(50)); // top 50 } public void testShortTest() { TSP tsp = new TSP(); // Load with default cities assertEquals(140, tsp.shortestPath(5)); // top 5 } public void testAnotherShortTest() { TSP tsp = new TSP(); // Load with default cities assertEquals(586, tsp.shortestPath(10)); // top 10 } public static Test suite() { TestSuite suite = new TestSuite(); // Only include short tests suite.addTest( new TestClassTwo("testShortTest")); suite.addTest( new TestClassTwo("testAnotherShortTest")); return suite; } }TestClassTwo的运行结果:
测试结果显示:testLongRunner()没有运行。
测试代码:(TestClassOne)
/** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ import junit.framework.*; public class TestClassOne extends TestCase { public TestClassOne(String method) { super(method); } public void testAddition() { assertEquals(4, 2+2); } public void testSubtraction() { assertEquals(0, 2-2); } }测试代码:(TestClassComposite)
/** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ import junit.framework.*; public class TestClassComposite extends TestCase { public TestClassComposite(String method) { super(method); } static public Test suite() { TestSuite suite = new TestSuite(); // Grab everything: suite.addTestSuite(TestClassOne.class); // Use the suite method: suite.addTest(TestClassTwo.suite()); return suite; } }TestClassComposite的运行结果:
测试结果显示:其执行了TestClassOne中的所有测试方法,执行了TestClassTwo中的suite方法。
上面我们了解到每一个方法执行前后都会有一个setUp和tearDown方法执行,然而suite的初始化以及清理工作与方法是分开的。过程相对复杂了点,需要提供所需测试的一个suite(无论通过什么样的方法)并且把它包装进一个TestSetup对象。
在上面代码的基础上进行的更改:
/** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ import junit.framework.*; import junit.extensions.*; public class TestClassTwo extends TestCase { private static TSP tsp; public TestClassTwo(String method) { super(method); } // This one takes a few hours... public void testLongRunner() { System.out.println("testLongRunner method running"); assertEquals(2300, tsp.shortestPath(50)); } public void testShortTest() { System.out.println("testShortTest method running"); assertEquals(140, tsp.shortestPath(5)); } public void testAnotherShortTest() { System.out.println("testAnotherShortTest method running"); assertEquals(586, tsp.shortestPath(10)); } public static Test suite() { TestSuite suite = new TestSuite(); // Only include short tests suite.addTest(new TestClassTwo("testShortTest")); suite.addTest(new TestClassTwo("testAnotherShortTest")); TestSetup wrapper = new TestSetup(suite) { protected void setUp() { oneTimeSetUp(); } protected void tearDown() { oneTimeTearDown(); } }; return wrapper; } public static void oneTimeSetUp() { // one-time initialization code goes here... System.out.println("suite_up......"); tsp = new TSP(); tsp.loadCities("EasternSeaboard"); } public static void oneTimeTearDown() { // one-time cleanup code goes here... System.out.println("suite_down......"); tsp.releaseCities(); } @Override protected void setUp() throws Exception { // TODO 自动生成的方法存根 System.out.println("setUp....."); super.setUp(); } @Override protected void tearDown() throws Exception { // TODO 自动生成的方法存根 System.out.println("tearDown....."); super.tearDown(); } }运行结果:
suite_up...... setUp..... testShortTest method running tearDown..... setUp..... testAnotherShortTest method running tearDown..... suite_down......注意:
你可以在同一个类中同时使用方法和suite的setup()和teardown()。
三、JUnit4使用
Junit4采用注释的机制,所以名字的命名并不那么重要了,但是最好规范一下。
命名规范:测试方法以Test开头
在JUnit4中可以有setUp和tearDown方法,但是测试方法的时候不会被执行。
在JUnit4.x中想直接使用Assert方法,则需要静态导入Assert:import static org.junit.Assert.*;
在JUnit4.x中测试类可以是一个普通类,也可以去继承一个类或者实现一个接口,要实现测试,只需要在要测试的方法之前加上@Test注释。
常用注解:
- @Before:在每个测试之前运行的代码
- @After :在每个测试之后运行的代码
- @Test:测试代码
- @Ignore:忽略的测试方法
- @BeforeClass:针对所有测试,只执行一次,且必须为static void
- @AfterClass:针对所有测试,只执行一次,且必须为static void
- @RunWith:指定测试类使用某个运行器
- @Parameters:指定测试类的测试数据集合
- @Rule:允许灵活添加或重新定义测试类中的每个测试方法的行为
- @FixMethodOrder:指定测试方法的执行顺序
@Test可以有两个参数:
- expected:检测方法是否抛出指定的异常(未抛出报错误)
- timeout:方法执行操作所耗费的毫秒数(超出指定时间报错误)
一个测试类单元测试的执行顺序为:
@BeforeClass –> @Before –> @Test –> @After –> @AfterClass
每一个测试方法的调用顺序为:
@Before –> @Test –> @After
通过测试组件测试多个类:
指定测试组件使用@RunWith
JUnit4新增的两个断言:
四、Hamcrest框架
镜像网站:http://hamcrest.org/
目的:增强JUnit,用一些语义通俗的方法来进行测试。要使用JUnit中的assertThat来进行断言。
需要静态导入Matchers包(import static org.hamcrest.Matchers.*;),否则就需要通过函数名称名称来调用了。
五、其它细节
1.测试
测试的具体方面:Right-BICEP
- Right——结果是否正确?
- B——是否所有的边界条件都是正确的?
- I——能查一下反向关联吗?
- C——能用其他手段交叉检查一下结果吗?
- E——你是否可以强制错误条件发生?
- P——是否满足性能要求?
无论如何,必须确定代码所做的和你所期望的一致。我们需要尽可能的从需求说明中获取信息,来全面设计测试方法,有时候文档是不明了的或者不完整的,至少我们可以自己发明一些需求来。从客户角度来看问题,而且要根据用户的反馈来调整自己的假设。在代码的整个生命周期中,“正确”的定义可能会不断在改变。
针对有大量测试数据的测试,我们会考虑用一个独立的数据文件来存储这些测试数据,然后让单元测试读取该文件。这是一个很好地选择,但是测试数据很有可能是不正确的,实际上测试数据比代码更有可能出错。因此当测试数据显示错误发生的时候,我们应该在怀疑代码之前先对测试数据检查两三遍。
另外,还有一些值得考虑的:代码本身是否并没有测试任何异常的情况。要实现这个功能,需要怎么来做呢?
一个原则是:对于验证被测方法是正确的这件事情,如果某些做法能够使它更加容易,那么就采纳它吧。
<2>边界条件(CORRECT Boundary Conditions)
找边界条件是做单元测试中最有价值的工作之一,因为bug一般就出现在边界上。
一些需要我们考虑的条件有:
- 完全伪造或者不一致的输入数据,例如一个名为“!*W:X\&Gi/w->g/h#WQ@”的文件。
- 格式错误的数据,例如没有顶级域名的电子邮件地址,就像fred@foobar这样的。
- 空值或者不完整的值(如0.0.0. “”和null)
- 一些与意料中的合理值想去甚远的数值。例如一个人的随书为10000岁
- 如果需求的是一个不允许出现重复数值的list,但是传入的是一个存在重复数值的list。
- 如果要求的是一个有序list,但是传入的是一个无序的list;或者反之。
- 事情达到的次序是错误的,或者碰巧和期望的次序不一致。例如,在未登录系统之前,就尝试打印文档
下面是测试边界接条件所需要考虑的几大反面:
- 一致性(Conformance)——值是否和预期的一致。
- 顺序性(Ordering)——值是否如应该的那样,是有序或者无序的。
- 区间性(Range)——值是否位于合理的最小值和最大值之内。
- 依赖性(Reference)——代码是否引用了一些不在代码本身控制范围之内的外部资源。
- 存在性(Existence)——值是否存在(例如,是否是非null,非0,在一个集合中等等)。
- 基数性(Cardinatity)——是否恰好有足够的值?
- 相对或者绝对的时间性(Time)——所有事情的发生是否是有序的?是否是在正确的时刻?是否恰好及时?
<3>检查反向关联
对于一些方法,我们可以使用反向的逻辑关系来验证他们。
例如:我们可以用对结果进行平方的方式来检查一个计算平方根的函数,判断测试结果是否和元数据是否接近;为了检查某条记录是否成功地插入了数据库,你也可以通过查询这条记录来验证。等等
需要注意的是:当你同时编写了原方法和反向测试时,一些bug可能会被在连个函数中都出现的错误所覆盖。在可能的情况下,应该使用不同的原理来编写反向测试。
<4>使用其他手段来实现交叉检查
通常来说,计算一个量会有一种以上的算法。我们可能基于效率或者其他特性来选择算法。但是测试中我们没必要考虑这些,所以我们可以用剩下的算法中的一个来交叉检测结果。
<5>强制产生错误条件
真实世界中,错误总是会发生:磁盘会满,网络连接会断开,电子邮件会多的像掉进了黑洞,而长须会崩溃。你应该通过强制引发错误,来测试你的代码是如何处理所有这些真实世界中的问题的。
我们存在的环境因素有:
- 内存耗光
- 磁盘用满
- 时钟出问题
- 网络不可用或者有问题
- 系统过载
- 调色板颜色数目有限
- 显示分辨率过高或者过低
<6>性能特性
一个检查起来会很有益处的部分是性能特性,而不是性能本身。
2.测试原则
- 建议创建一个站们的source folder-->test来编写测试类代码
- 测试类的包应该保持和需要测试的类的一致性
- 测试单元中的每一个测试方法都必须可以独立运行,没有顺序,而且测试方法之间不能有任何的依赖性
3.Mock测试
简介:mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。
- 真实对象具有不可确定的行为(产生不可预测的结果,如股票行情)
- 真实对象很难被常见
- 真实对象的某些行为很难出发(如网络错误)
- 真实对象令程序的运行速度很慢
- 真实对象有(或者是)用户界面
- 测试需要询问真实对象他是如何被调用的(例如,测试可能需要验证某个回调函数是否被调用了)
- 真实对象实际上并不存在(当需要和其他开发小组,或者新的硬件系统打交道的时候,这是一个普遍问题)
借助于mock对象,我们就可以解决上面的所有问题。在使用mock对象进行测试的时候,总共有3个关键步骤,分别是:
- 使用一个借口来描述这个对象
- 为产品代码实现这个接口
- 以测试为目的,在mock对象中实现这个接口
因为被测试代码只会通过接口来引用对象,所以它完全可以不知道它引用的究竟是真实对象还是mock对象。
下面是一个详细的示例:(具体讲解在《单元测试之道Java版:使用JUnit》这里不再详细叙述)
Environmental.java
/** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Various methods particular to our runtime environment */ public interface Environmental { public long getTime(); // Other methods omitted... public void playWavFile(String name); }
SystemEnvironment.java
/** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing" ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. Visit * www.PragmaticProgrammer.com */ public class SystemEnvironment implements Environmental { public long getTime() { return System.currentTimeMillis(); } // other methods ... public void playWavFile(String name) { // Left as an exercise to the reader... } }MockSystemEnvironment.java
/** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing" ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. Visit * www.PragmaticProgrammer.com */ public class MockSystemEnvironment implements Environmental { private long current_time; private boolean playedWav = false; public long getTime() { return current_time; } public void setTime(long aTime) { current_time = aTime; } public void playWavFile(String filename) { playedWav = true; } public boolean wavWasPlayed() { return playedWav; } public void resetWav() { playedWav = false; } // ... }Checker.java
/** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ import java.util.Calendar; public class Checker { public Checker(Environmental anEnv) { env = anEnv; } /** * After 5 o'clock, remind people to go home by playing a whistle */ public void reminder() { Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(env.getTime()); int hour = cal.get(Calendar.HOUR_OF_DAY); if (hour >= 17) { // 5:00PM env.playWavFile("quit_whistle.wav"); } } // ... private Environmental env; }TestChecker.java
/** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing in Java with JUnit" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ /** * Excerpted from the book, "Pragmatic Unit Testing" * ISBN 0-9745140-1-2 * Copyright 2003 The Pragmatic Programmers, LLC. All Rights Reserved. * Visit www.PragmaticProgrammer.com */ import junit.framework.*; import java.util.Calendar; public class TestChecker extends TestCase { public void testQuittingTime() { MockSystemEnvironment env = new MockSystemEnvironment(); // Set up a target test time Calendar cal = Calendar.getInstance(); cal.set(Calendar.YEAR, 2004); cal.set(Calendar.MONTH, 10); cal.set(Calendar.DAY_OF_MONTH, 1); cal.set(Calendar.HOUR_OF_DAY, 16); cal.set(Calendar.MINUTE, 55); long t1 = cal.getTimeInMillis(); env.setTime(t1); Checker checker = new Checker(env); // Run the checker checker.reminder(); // Nothing should have been played yet assertFalse(env.wavWasPlayed()); // Advance the time by 5 minutes t1 += (5 * 60 * 1000); env.setTime(t1); // Now run the checker checker.reminder(); // Should have played now assertTrue(env.wavWasPlayed()); // Reset the flag so we can try again env.resetWav(); // Advance the time by 2 hours and check t1 += 2 * 60 * 60 * 1000; env.setTime(t1); checker.reminder(); assertTrue(env.wavWasPlayed()); } }
测试Servlet
基于Web的Servlet需要容器(常用的是Tomcat)和浏览器,运行过程和环境相对复杂,这是一个交互的过程,看起来无法完成自动化的单元测试,幸运的是Mock对象可以解决这个问题。
(这部分没有理解透,这里还使用了easymock)
参考资料:
《单元测试之道Java版:使用JUnit》
Junit使用教程(二)
单元测试——junit