Junit:局部变量和void方法

时间:2016-10-01 19:13:31

标签: java junit mocking mockito

我对单元测试相当新,并且已经在网上阅读了大量资料,但我在解决问题方面遇到了一些麻烦。

例如:如果我有以下代码:

public class RandomClass
{
  int a = 4;
  public void foo(Object obj)
  {
    if(a == 4)
    {
      AnotherObject anotherObj = new AnotherObject();
      anotherObj.setAttribute(obj.getFiled());
      //Method call that will be suppressed 
      Anotherclass.anotherMethod(anotherObj);
    } 
  }
}

我想过写这样的junit测试用例:

@Test
public void testFoo()
{
  int a=4;
  RandomClass randomClass = new RandomClass();
  Object object = new Object();
  object.setField("hey");
  randomClass.foo(object);
}

我在这里有几个问题。 我怎样从junit设置整数a?我现在设置它的方式并不会影响单元测试用例。当我调试单元测试时,a的值为NULL,因此它永远不会通过if条件!

此外,方法foo返回一个void,那么我可以测试/断言什么?

2 个答案:

答案 0 :(得分:1)

编写单元测试时有两种主要技巧:

  1. 检查您所在班级的外部合同。含义:您尝试编写 RandomClass 的测试用例,该测试用例知道没有关于 AnotherClass 。相反,您的测试代码仅观察 RandomClass 对象的行为。换句话说:你真的不关心 RandomClass 的内部实现细节 - 因为你可以通过检查 RandomClass 对象来观察你想要看到的所有东西调用具有特定参数的方法时返回。有时你会通过添加(包受保护的)getter方法来实现这一目的,这些方法允许你检查你所测试的类的一些内部状态。
  2. 但有时那可能不够“好”;例如,当您知道您的测试类必须使用其他一些对象来完成其工作时。在这种情况下,您应该查看模拟对象。在您的情况下,您可能想要创建 AnotherClass 的模拟实例;然后你会使用依赖注入提供该对象到你正在测试的类中。
  3. 您知道,您实际上编写了“难以测试”的代码 - 因为您在生产代码中为 AnotherClass 调用了 new 。这似乎不是什么大问题,但取决于 AnotherClass 的内容......你真的不应该这样做!

    无论如何;我建议您查看这些videos以了解如何编写更适合单元测试的代码。

答案 1 :(得分:1)

测试通常以“设置”,“准备”或“排列”步骤开始,在此步骤中,它会创建或修改被测对象,使其处于特定测试所需的状态。

因此,如果a对象中的字段RandomClass需要具有值4(例如),则测试需要创建将此值作为构造函数传递的对象参数,通过调用setter方法或直接访问该字段来设置对象中的值。在最坏的情况下,您可能需要使用Reflection来设置字段,但这表明正在测试的类中存在设计问题。

下一步是练习测试中的代码。这是“安排,行动,断言”术语中的“行为”步骤(简称AAA)。

最后,最后一步是“断言”(验证)正在测试的代码做了应该做的事情。

如果正在测试的方法具有void返回类型,那么测试应该通过状态验证或行为验证来验证它是否达到预期效果。

在第一种情况下,测试会在被测对象中调用一些getter方法,并在某种“断言”中使用它(例如,assertEquals(expectedValue, actualValue))。

在第二种情况下,测试将使用一些模拟库,以验证期望的调用是从测试中的代码到一个或多个依赖项(其他对象或类所在的类)在测试中取决于)。例如,此处测试可以验证RandomClass#foo确实调用Anotherclass.anotherMethod(...)