6

我正在尝试编写一个需要确认是否调用方法的单元测试。我正在使用 JUnit、Mockito 和 PowerMock。

公共类发票
{

  受保护的无效 createInvoice()
  {
    // 这里随机的东西
    markInvoiceAsBilled("57");
  }

  protected void markInvoiceAsBilled(字符串代码)
  {
    // 标记为已收费
  }
}

所以,这里我的测试系统是Invoice. 我正在运行这个测试:

  公共类 InvoiceTest
  {
    @测试
    公共无效 testInvoiceMarkedAsBilled()
    {
      发票 sut = new Invoice();
      发票 sutSpy = spy(sut);

      sut.createInvoice();

      // 我想验证是否调用了 markInvoiceAsBilled()
    }
  }

这个例子只是实际代码的一个例子......

我的问题是,mockito 说你只能验证是否在模拟对象上调用了一个方法......但我不想模拟这个对象,因为它是我正在测试的对象。我知道你可以监视你正在测试的对象,所以这就是我尝试的:

  验证(sutSpy).markInvoiceAsBilled(“57”);

我想做的事是不可能的吗?还是我只是走错路了?

谢谢大家 :)

4

2 回答 2

10

我不确定您尝试做的是否是处理事情的最佳方式。

我不关心验证Invoice.createInvoice()调用内部私有方法markInvoiceAsBilled()- 而是测试调用createInvoice()以您期望的方式更改 Invoice 对象的状态 - 即status现在BILLED或类似的方式。

换句话说——不要测试调用了哪些方法createInvoice()——测试调用这个方法后,对象的状态是你所期望的。

于 2012-09-14T17:47:17.023 回答
1

我同意matt-b的回答。话虽如此,根据用例和方法的复杂性,您可以重新设计您的单元,以便对其进行测试。

例如说你的对象变得更加复杂,例如

public A {
  public a() {
    b();
    c();
  }

  public b() { /** hairy code, many branches to test */ }
  public c() { /** hairy code, many branches to test */ }
}

用测试覆盖 b 和用测试覆盖 c 是直截了当的,但覆盖 a 似乎很麻烦,因为您依赖于方法 b 和 c。

考虑一下这个设计

public A {
  private final Dep mDep;

  public a() {
    mDep.b();
    mDep.c();
  }

  public b() { 
    mDep.b(); 
  }

  public c() { 
    mDep.c();
  }

  // dependency abstraction we create to help test
  static class Dep {
    public b() { /** hairy code, many branches to test */ }
    public c() { /** hairy code, many branches to test */ }
  }
}

现在, testing A.aA.b并且A.c只需要您验证您的mDep被调用(以及该方法所做的任何其他事情)。另外,你测试A.Dep.bA.Dep.c方法。

于 2017-09-01T17:38:06.180 回答