Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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 :)

like image 980
Trevor Avatar asked Sep 14 '12 17:09

Trevor


2 Answers

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.

like image 182
matt b Avatar answered Oct 11 '22 09:10

matt b


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.

like image 43
Simon Bocanegra Thiel Avatar answered Oct 11 '22 10:10

Simon Bocanegra Thiel