How to verify if method is called on System under test (not a mock)

心不动则不痛 提交于 2020-01-03 10:02:09

问题


I'm trying to write a unit test that needs to confirm if a method is called or not. I'm using JUnit, Mockito and PowerMock.

public class Invoice
{

  protected void createInvoice()
  {
    // random stuff here
    markInvoiceAsBilled("57");
  }

  protected void markInvoiceAsBilled(String code)
  {
    // marked as billed
  } 
}

So, here my system under test is Invoice. I'm running this test:

  public class InvoiceTest
  {
    @Test
    public void testInvoiceMarkedAsBilled()
    {
      Invoice sut = new Invoice();
      Invoice sutSpy = spy(sut);

      sut.createInvoice();

      // I want to verify that markInvoiceAsBilled() was called
    }
  }

This example is just an example of what the actual code looks like....

My problem is that mockito says you can only verify if a method is called on a mocked object... but I don't want to mock this object, as it's my object under test. I know that you can spy on the object you're testing, so here's what I tried:


  verify(sutSpy).markInvoiceAsBilled("57");

Is what I'm trying to do not possible? Or am I just going about it the wrong way?

Thanks everyone :)


回答1:


I'm not sure if what you are attempting to do is the best way to go about things.

I wouldn't concern myself with verifying that Invoice.createInvoice() calls an internal, private method markInvoiceAsBilled() - instead test that calling createInvoice() changes the state of the Invoice object in the way you expect - i.e., that status is now BILLED or something similar.

In other words - don't test what methods are called by createInvoice() - test that after calling this method, the state of the object is what you expect.




回答2:


I agree with matt-b's answer. That being said, depending on the use case and the complexity of the method, you can redesign your unit so that it can be tested.

Say for example your object gets much more complicated, e.g.

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

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

Covering b with tests and c with tests is straight-forward, but covering a would seem like a hassle since you depend on methods b and c.

Consider instead this design

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 */ }
  }
}

Now, testing A.a, A.b and A.c just requires you to verify your mDep is called (among whatever else the method does). Separately, you test A.Dep.b and A.Dep.c methods.



来源:https://stackoverflow.com/questions/12429157/how-to-verify-if-method-is-called-on-system-under-test-not-a-mock

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!