我想寻求帮助和建议,哪种情况是正确的方法(可能很简单,但我只是从JUnit开始)。这是我的代码的一部分
public boolean arrayListEmpty()
{
if(numericalSequence.isEmpty() == true)
return true;
else
return false;
}
这是模型中的一个公共方法,我想我应该测试一下,如果我的数值序列为空,则返回true。我不能直接调用numericSequence.isEmpty(在我需要的控制器中)检查它,因为它是私有的。 显而易见的是要检查
assertEquals(true, test.arrayListEmpty());
所以我的问题是关于建议我应该使用其他哪些主张/应该预测哪些情况可以提出的建议。我应该在Test方法中用一些值填充numericSequence并对其进行断言吗? (对我而言,这不是必需的,因为插入序列中的任何值都不是null,但是可能并不容易)
答案 0 :(得分:2)
首先,欢迎您使用Stack Overflow!
看着您的问题,听起来您是单元测试的新手(如果我错了,请纠正我)。因此,我将答案分为两个部分: (1)回答您的问题,以及(2)为如何编写良好的测试和可测试的类提供总体指导。
1。回答您的问题
您可以在这里想到更多用例:
numericalSequence
是null
会发生什么?numericalSequence
有1个元素怎么办?numericalSequence
具有null元素怎么办?上述某些情况可能无法实现,具体取决于您的类的设置方式,但这是一项值得拥有的测试,因此,违反这些测试用例之一的“先前约定的行为”的任何类更改都将失败
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
是否为空arrayListIsEmpty
为null或具有null元素时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
永远不会null
(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());
}
我打算展示几件事:
希望这会有所帮助。