【问题标题】:Junit: local variables and void methodsJunit:局部变量和 void 方法
【发布时间】:2016-10-01 19:13:31
【问题描述】:

我对单元测试还很陌生,并且已经在网上阅读了很多资料,但我在搞清楚东西时遇到了一些麻烦。

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

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 那么我可以测试/断言什么?

【问题讨论】:

  • 您的代码不正确。如果变量aRandomClass 中不是静态的,您将无法在静态方法foo 中检查其值
  • 哦,我明白了,如果 foo 不是静态方法,我如何检查 a 的值?
  • 不是junit相关的情况,是访问类字段和封装的情况

标签: java junit mocking mockito


【解决方案1】:

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

  1. 检查您的被测类的外部合同。含义:您尝试为 RandomClass 编写对 AnotherClass一无所知的测试用例。相反,您的测试代码只观察 RandomClass 对象的行为。换句话说:你真的不关心 RandomClass 的内部实现细节 - 因为你“想看到”的所有东西都可以通过检查 RandomClass 对象来观察当您调用具有特定参数的方法时返回。有时,您可以通过添加(包保护的)getter 方法来检查被测类的某些内部状态。
  2. 但有时这可能还不够“好”;例如,当您知道您的测试类必须使用其他一些对象来完成其工作时。在这种情况下,您应该查看 mocking 对象。在您的情况下,您可能想要创建 AnotherClass 的模拟实例;然后您将使用依赖注入以便提供该对象到您的测试类。

您看,您实际上编写了“难以测试”的代码 - 因为您在生产代码中为 AnotherClass 调用 new。这似乎没什么大不了的,但取决于 AnotherClass 是关于什么的......你真的不应该这样做!

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

【讨论】:

    【解决方案2】:

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

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

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

    最后,最后一步是“断言”(验证)被测试的代码是否符合预期。

    如果被测试的方法有void 返回类型,那么测试应该通过state 验证或behavior 验证来验证它是否符合预期。 p>

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

    在第二种情况下,测试将使用一些 mocking 库来验证预期调用是从被测代码对一个或多个依赖项(该类所在的其他对象或类)进行的待测取决于)。例如,这里的测试可以验证RandomClass#foo 确实调用了Anotherclass.anotherMethod(...)

    【讨论】:

    • 这里的所有答案都非常有帮助。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多