junit - JUnit 我应该使用什么断言
问题描述
我想寻求帮助和建议在我的情况下什么是正确的方法(可能很容易,但我只是从 JUnit 开始)。这是我的代码的一部分
public boolean arrayListEmpty()
{
if(numericalSequence.isEmpty() == true)
return true;
else
return false;
}
这是模型中的一个公共方法,我想我应该测试它,如果我的数字序列为空,它只会返回 true,如您所见。我不能直接调用 numericSequence.isEmpty (在我需要它的控制器中)检查它,因为它是私有的。很明显的事情是检查
assertEquals(true, test.arrayListEmpty());
所以我的问题是关于建议我应该使用哪些其他断言/我应该预测哪些情况会出现。我应该在测试方法中用一些值填充 numericSequence 并断言它吗?(对我来说没有必要,因为插入到序列中的任何值 = 不为空,但可能并不那么容易)
解决方案
首先,欢迎来到 Stack Overflow!
看看你的问题,听起来你是单元测试的新手(如果我错了,请纠正我)。所以,我将把我的答案分成两个部分;(1) 回答你的问题,(2) 给出如何编写好的测试和可测试类的大致方向。
1. 回答你的问题
您可以在这里想到更多用例:
- 如果
numericalSequence
是会发生什么null
? - 如果
numericalSequence
有 1 个元素怎么办? - 如果
numericalSequence
有一个空元素怎么办?
根据您的类的设置方式,上述某些情况可能无法实现,但这是一个值得进行的测试,因此违反这些测试用例之一的“先前约定的行为”的类的任何更改都会失败。
2. 编写好的测试
对于如何编写好的测试没有严格的指导方针,但是,如果您将代码构建为可测试的,您会发现编写好的测试变得更容易,并且不会那么繁琐。请允许我解释一下。
注意:这不是一个全面的指南,但旨在开始您的旅程,了解如何编写更好的代码和更好的测试
所以假设一个需要测试的类是这样写的:
class MyClass {
// NOTE: This is not `final`
private List<Integer> numericalSequence;
public MyClass() {
this.numericalSequence = new ArrayList<>();
}
public void doSomething(Integer x) {
if (x < 0) {
numericalSequence = new ArrayList<>();
} else {
numericalSequence.add(2 * x);
}
}
public boolean arrayListEmpty() {
// NOTE: Your sample code can be reduced to this one-liner
return numericalSequence.isEmpty();
}
}
以下是上述代码中的一些缺陷:
doSomething
方法允许为空(装箱整数)值,因此可以NullPointerException
在第一if
条语句中导致。- 该
numericalSequence
成员不是最终的,因此将其设置为的代码在方法null
内是有效的doSomething
- 该
arrayListIsEmpty
方法不检查是否numericalSequence
为空 - 如果我想测试为 null 或具有 null 元素
arrayListIsEmpty
时的行为numericalSequence
方式,则很难做到这一点,除非您知道如何让类进入该状态。
如果该类被重写为以下内容:
class MyClass {
private final List<Integer> numericalSequence;
public MyClass() {
this(new ArrayList<>());
}
// Should be made public only if the classes that use this one needs to
// initialize this instance with the sequence. Make this package-private
// otherwise.
public MyClass(List<Integer> sequence) {
this.numericalSequence = sequence;
}
public void doSomething(int x) {
if (x < 0) {
// COMPILE ERROR: Cannot assign to a final member
// numericalSequence = new ArrayList<>();
numericalSequence.clear();
} else {
numericalSequence.add(2 * x);
}
}
public boolean arrayListEmpty() {
return numericalSequence == null || numericalSequence.isEmpty();
}
}
关于上述结构需要注意的几点:
- 有两个构造函数;默认调用将整数列表作为序列的那个,以便它重用两者都需要共享的任何逻辑。此示例中没有逻辑,但希望您很快就会遇到。
- 该
doSomething()
方法不接受Integer
值,但int
值确保它x
是 nevernull
(Java 数字原始类型不能是null
)。这也意味着,numericalSequence
不能通过doSomething()
. - 由于
numericalSequence
可以从此类外部初始化,因此该arrayListEmpty()
方法确保检查numericalSequence
是否null
真的为空。
现在您可以像这样编写测试用例:
@Test
public void arrayListEmpty_WhenListIsNull() {
MyClass test = MyClass(null);
assertTrue(test.arrayListEmpty());
}
@Test
public void arrayListEmpty_WhenListIsEmpty() {
MyClass test = MyClass();
assertTrue(test.arrayListEmpty());
}
@Test
public void arrayListEmpty_WhenListHasOnlyOneNonNullElement() {
List<Integer> sequence = new ArrayList<>();
sequence.add(0);
MyClass test = new MyClass(sequence);
assertFalse(test.arrayListEmpty());
}
@Test
public void arrayListEmpty_WhenListHasOnlyOneNullElement() {
List<Integer> sequence = new ArrayList<>();
sequence.add(null);
MyClass test = new MyClass(sequence);
assertFalse(test.arrayListEmpty());
}
由于doSomething()
添加/清除序列,因此在编写测试以doSomething()
确保调用并通过检查返回值来验证类的状态arrayListEmpty()
。
例如:
@Test
public void doSomething_WhenInputLessThanZero() {
List<Integer> sequence = new ArrayList<>();
sequence.add(0);
MyClass test = new MyClass(sequence);
test.doSomething(-1);
assertTrue(test.arrayListEmpty());
}
我的意图是展示几件事:
- 将您的测试用例组织得小而简洁
- 将您的课程设计为易于测试
希望这可以帮助。
推荐阅读
- python - ModuleNotFoundError:没有名为“jmetal”的模块
- reactjs - Firebase 存储安全错误 - 错误地标记为网络钓鱼
- python - 如何修复 FileNotFoundError:[Errno 2] 没有这样的文件或目录:没有
- python - psycopg2从python字符串传递时间戳
- javascript - Google Apps 脚本(网络部署)自动重新加载页面
- python - 说单元测试失败但仅仅因为测试脚本被破坏的正确方法是什么?
- r - XGBoost 交叉验证错误: slice.xgb.DMatrix 中的错误
- java - 无法连接到 API 出现错误 java.net.UnknownHostException
- javascript - javascript - 进行数千次 $.getJSON 调用以避免 ERR_INSUFFICIENT_RESOURCE 的正确方法
- python - 将 JSON 列表读入 Python 类的 Pythonic 方法