问题:
当为一个产品类编写了好几个测试,它们含有重复的代码。因为我们知道重复的代码是软件中很多问题的根源,怎么 消除代码中的重复性。
背景:
为同一个产品类编写几个测试的时候,你最先注意到的模式之一就是每个测试开始的那几行代码总是很相像。每个测试都有三个基本的组成部分:创建一个对象,调用一些方法,检查结果。每个测试的第二部分总是不同的,对不同方法的调用可以区别不同的测试:"如果用这些参数调用构造方法,希望看到这样的结果;但是如果传递了空值,那么构造方法应该抛出那样的异常"。
测试的第3部分,检查结果,这完全依赖于你所调用的方法,如果测试调用的是不同的方法,当然期望的结果也是不同的。一般情况下,在这部分,只有在反复调用同一个方法的时候才会有重复代码出现。
然而,创建对象会产生测试之间的重复代码,而且绝大部分重复的代码都出现在这里,在一个类中除了构造方法以外还有很多方法需要测试,所以一旦为这个类编写了第二个测试,就重复了第一个测试中"创建一些对象"的部分,因为很可能用相同的参数调用了相同的构造方法,这样的重复代码实在是很常见,所以如果 Junit能有一种内置的机制来消除它,那就再好不过了。
那么如果将要测试的对象称为测试模块:一种对象的"配置",其行为是可以预见的。这样的话,我们可以将测试第一部分----"创建一些对象"称为“创建一个测试模块”。目的是创建一些对象并且将其初始化成某种已知的状态,以便在使用它们调用一些方法的时候,可以预见到结果。
技巧:
从测试中找出重复的测试模块代码,将这些代码移动到一个叫做setUp()的方法里面。修改后的代码可能不需要编译,因为现在是在setUp()方法中声明变量,然后在测试中使用这些变量。将这些变量放在实例级的参数域中,这样setUp()和测试代码都可以使用它们。因为每个测试是执行在其自己的实例中,所以不必担心在不同测试之间实例级的参数域会被错误地改变。在执行测试的时候,test runner会在每个测试之前调用setUp()方法。测试类中的每个测试都可以使用这个通用的方法初始化。
代码演示:
下面代码Money JavaBean及方法就不给出,可以根据测试代码,自己推出
1. public class MoneyTest extends TestCase{ 2. 3. public void testAdd(){ 4. Money added = new Money(12,50); 5. Money augend = new Money(12,50); 6. Money sum = added.add(augend); 7. assertEquals(2500,sum.inCents()); 8. } 9. public void testNegate(){ 10. Money money = new Money(12,50); 11. Money opposite = money.negate(); 12. assertEquals(-1250,opposite.inCents()); 13. } 14. 15. public void testRound(){ 16. Money money = new Money(12,50); 17. Money rounded = money.roundToNearestDollar(); 18. assertEquals(1300,rounder.inCents()); 19. } 20. } |