如何测试一个没有返回值的方法

来源:百度文库 编辑:神马文学网 时间:2024/07/04 17:02:19
在JUnit 中,如果一个方法没有返回值,那么我们就没有办法用 assertEquals() 直接来比较我们所期望的值和方法执行后的所返回的实际值之间的差别。但是我们知道,一个方法应该要么有返回值要么又可以观察到的副作用,否则这个方法就可以被视作什么事情都没有做。所以,如果一个方法没有返回值,那么我们就应该根据它的可观察的副作用来进行测试。
举一个例子,测试向堆栈中压入元素的方法 push()。假设 Stack 类的 push() 方法不会返回任何值。我们可以采取以下步骤来测试 push() 方法:
1、建立一个空的堆栈;
2、判断该堆栈的栈顶是否是要压入的元素;
3、将一个元素压入堆栈;
4、判断堆栈顶部的元素是否是刚才压入的元素。
用Java 语言翻译过来就是:
public class PushToStackTest extends TestCase {
public void testStackPush {
Stack stack = new Stack();
assertFalse(stack.pop().equals("item"));
stack.push("item");
assertEquals("item", stack.pop());
}
}
大家会注意到,这个测试方法中用到了 Stack 类的另外一个方法 pop(),我们测试过 pop() 吗?如果要对 pop() 进行测试的话,显而易见我们必定要使用到  push()。我们既然没有通过对  push() 的测试,怎么能够保证可以正确的测试 pop() 呢?既然我们不能测试 pop() 的正确性,怎么能够断定 testStackPush() 是正确的呢?唔,这是一个“鸡生蛋蛋生鸡”的问题。 从这个循环怪圈里面跳出来,记住,我们真正要测试的是对象的行为,而不是对象的方法!在 testStackPush() 中我们要测试的是向堆栈压入元素的行为,而不是 Stack 类的 push() 方法。在测试中,我们可能要用到 Stack 的  push()、pop()、clear()、peek(),使用这些方法都是为了测试是否能够正确地压入一个元素。所有的这些方法组合在一起,来实现一种功能、一种行为。
可能存在这么一种情况,单个方法的实现代码是错误的,但是它们组合起来却实现了正确的行为。这种情况,我们是否认为这是一种软件缺陷呢?答案可能会令人吃惊:不。因为对于JUnit 用户来说,应当认为测试就是标准、就是规格说明书。正因为如此,JUnit 程序员需要书写足够全面的测试代码来测试对象的行为,保证不会因为偶然的情况使得有缺陷的代码逃过单元测试。
另外说一个话题,大家可以在上面所示的Java 代码中看到JUnit 中只有判断期望值和实际值相等的断言方法,却没有相反的方法:assertNotEquals()。当然,在某些JUnit 的扩展项目中我们可以找到这个方法,例如在JUnit-addons 中,但是这还没有成为JUnit 的一部分。现在也有很多JUnit 社区在呼吁将 assertNotEquals() 添加到JUnit 中去。希望我们能够在JUnit 4 中看到这个方法,这样我们就不用费一番周折得用“equals() 的否定形式”来表示“期望值和实际值不等”这么一个简单的断言了。