测试一个返回类型为void的方法。

8

我是软件测试新手。在一篇教程中,我看到可以这样测试某些方法:

@Test
 public void testMultiply() {
   MyClass tester = new MyClass();
   assertEquals("10 x 5 must be 50", 50, tester.multiply(10, 5));
 } 

我需要将一些参数传递给一个方法,并获得返回值。
但在我的情况下,有些类没有任何参数和返回值:

ArrayList al = new ArrayList();

public void Main(){
  methodA();
  methodB();
}

public void methodA(){
  // connect to URL
  // get some data
  for(int i=0; i<someThing; i++){
    al.add(data);
  }
}
public void methodB(){
  // do something with al
}

还可以对它们进行测试吗?例如,是否可以测试methodA()中来自URL的正确值。


当然可以。看起来methodA()正在修改ArrayList的内部状态,因此您可以使您的测试类在执行该方法之前和之后检查列表的内容。 - azurefrog
是的,这取决于重要的是什么,您可以使用Mockito来验证是否调用了实现,也可以验证它所改变的对象。 - StackFlowed
当然。通常情况下,如果在没有参数和返回值的函数调用过程中没有出现错误,那么这个函数就可以工作了。当然,这并不完全正确。为此,您可以使用调试器来测试程序的流程。 - nbro
可能是如何使用Junit测试工具测试void方法?的重复问题。 - Joe
5个回答

6
可以测试不返回任何东西(void)的方法,但必须测试该方法的副作用。否则这样的方法是无用的。这里的副作用是改变了al。按照现有编写方式,该类没有其他公开al的方法。添加一个getter方法来返回ArrayListArrayList中的特定元素。然后你的测试方法可以调用getter方法来检索值,并将其与预期值进行比较。

2
我应该添加这个方法只是为了让测试类调用它吗?即使我在代码中实际上并不需要它? - Evgenij Reznik
这些数据是如何被使用的?如果它被其他方法(例如methodB)使用,那么你可以使用methodB并测试其副作用。 - rgettman
@user1170330 是的。你正在编写一个可测试的组件,这意味着要编写足够的访问器来进行测试。如果这些访问器在生产环境中不应该被调用,请将其记录下来。 - Jeff Bowman

2

没有参数的方法用于返回值或副作用,因此这些方法的测试包括以下三个步骤:

  • 在调用无参方法之前,将被测试对象设置为初始状态
  • 调用无参方法
  • 检查无参方法的返回值或副作用

最后一步可以检查被测试对象的新状态,也可以检查其在系统整体环境中的工作结果。

下面是一个小例子:

class Calculator {
    private int left, right, result;
    public void setLeft(int val) { left = val; }
    public void setRight(int val) { right = val; }
    public int getResult() { return result; }
    public void add() { result = left + right; }
    public void multiply() { result = left * right; }
}

您可以这样测试它的multiply()方法:
@Test
public void testMultiply() {
    // Set the object being tested to the initial state 
    Calculator tester = new Calculator();
    tester.setLeft(5);
    tester.setRight(10);
    // Call the method
    tester.multiply();
    // Check the new state
    assertEquals("10 x 5 must be 50", 50, tester.getResult());
}

这个示例测试方法的副作用。测试有返回值但没有副作用的方法将把方法调用与断言行的检查结合起来。


值得澄清的是:没有参数和返回值的方法用于它们的副作用。没有参数但有返回值的方法不需要具有副作用(例如getter方法)。 - chiastic-security
@chiastic-security 这是一个公正的观察,非常感谢! - Sergey Kalinichenko

2

是的,你可以测试一个没有参数的方法。

举个例子,考虑一下ArrayList.clear()方法。它的作用是清空ArrayList,使其大小变为零。你可以通过以下步骤来测试这个方法:

  1. 创建一个ArrayList arr
  2. 向其中添加一些元素;
  3. 调用arr.clear()
  4. 检查assertEquals(arr.size(),0)

换言之,你需要设置一个不希望的状态(size()>0),然后调用应该对状态产生可预测影响的方法(将size()设置为0),最后检查效果是否符合预期。


如果在我的实现中实际上不需要size()方法,那该怎么办?我应该创建它以便测试类可以使用吗? - Evgenij Reznik
1
好的,重点是被测试的方法必须对状态产生一定影响,并且这种状态变化必须可以用你已有的方法检测到...否则,要么这个方法是无意义的,要么你需要更多的方法!换句话说,如果你没有任何方法会根据你是否清空了ArrayList而表现出不同的行为,那么清空它就毫无意义。 - chiastic-security

1

如果您在其他方法中将这些方法用作副作用,则可以测试这些方法。例如-

public class test{
public int i=0;
public void incrementIngeterValue()
{
  //doing something and 
   i++;
}

public boolean incremented()
{
  //some logic to check what is current i value
  int x = incrementIngeterValue();

  if(x==i)
       return false; // value not incremented
  else
       return true // in this case you can make sure this value is incremented by 1.


}

所以你可以测试递增方法来检查i值是否增加了1,使用这种方法,你内部测试递增整数值()没有参数和返回值。

在你的情况下,a1在两种方法中都受到影响。有些地方你正在使用这个a1。


0
在这种情况下,您正在尝试测试调用的副作用,而不是调用本身的输出(例如返回值)。您可以通过多种方式进行测试:
  1. 如果副作用是可见的,请测试它们的结果是否符合您的期望
  2. 如果副作用不容易看到,因为它们调用外部接口,请使用模拟框架,例如PowerMock,将外部接口替换为模拟对象,以便您可以观察和针对外部接口的调用进行测试
  3. 重新设计您的接口以使其更易于测试。 :)

在您的特定情况下,我会添加一个访问器来检查其内容是否在调用AMethod()后与预期相匹配。

一般来说,在单元测试中,您不希望连接到外部URL、数据库等,因为这很慢且昂贵。您希望用可以模拟它们的数据提供程序替换这些调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接