Unit Test to verify number of times lazy initialization logic is executed for a data member I'll write a small simulation of my actual class first to request insights on unit testing one of the behaviors of this class. Here is my class A:

public class A {
    private final String a;
    private final String b;
    private String c;

    public A(final String a, final String b) {
       this.a = a;
       this.b = b;
       this.c = null;
    }

    public getC() {
       if (this.c==null) {   
          // Logic to compute value of this.c using this.a and this.b
          // set this.c
       }

       return this.c; 
    }
}


In the above class I'm doing lazy initialization of a data member c. Responsibility of class A is to  compute this.c from this.a and this.b and cache it so that there is no need to compute it again on future invocation of getC. Class A has only this responsibility.

I want to write a unit test to verify that on Multiple invocations of getC() method on the same instance of class A, logic for computing this.c should be executed only once. Could anyone please help in figuring out, how can I write this unit test ? One way I can see is delegating the logic of computing this.c to another class B and then making class A dependent on class B so that a mock of class B can be injected during testing. After injection of mock of B, Mockito's feature to verify number of times method invocation happens on a mock can be used. But Class A has only one responsibility of computing this.c and delegating that responsibility to another object is looking like an overkill to me.
Delegate the computation of a and b to a method, say, .compute(). Since we want to spy this method's execution, we will suppose that we have Guava and its useful @VisibleForTesting annotation, and make the method protected:

@VisibleForTesting
protected String compute(String a, String b) { // code here }


Now, code written using Mockito and TestNG (with test file in same package than class A, so that the compute() method is visible):

@Test
public void computationOfCHappensOnlyOnce()
{
    final String a = "whatever";
    final String b = "you want";

    final A spy = spy(new A(a, b));

    for (int i = 0; i &lt; 10; i++)
        spy.getC();

    verify(spy, times(1)).compute(eq(a), eq(b));
}


Note: the way your class is currently written, it is NOT thread safe. The quick, coarse way to fix it is to make .getC() synchronized.

EDIT Discussion on a different design to get the value of c

This requires a creation of a new factory class for instances of class A; it would have the responsibility to create new instances and compute c:

// if the class is a singleton...
final FactoryForA factory = FactoryForA.getInstance();

final A a = factory.newA(a, b);

// This calls back to the factory to compute c:
a.getC();


The A class needs to implement .equals() and .hashCode() (on fields a and b but obviously not c!). Also, it has a constructure which is now package private (so that the factory can access it) and whose prototype is:

final String a, b;
final FactoryForA factory;
// No `c` member, see below

A(String a, String b, FactoryForA factory) 
{
    this.a = a; this.b = b; this.factory = factory;
}

public getC()
{
    return factory.computeC(this);
}


Now for the factory itself: it has an ExecutorService and a Map&lt;A, FutureTask&lt;String&gt;&gt;. Here is the code of computeC():

// instance variables of the factory
private final ExecutorService service
    = Executors.newFixedThreadPool(5); // for example
private final Map&lt;A, FutureTask&lt;String&gt;&gt; map = new HashMap&lt;&gt;();

// package private
String computeC(final A a)
{
    FutureTask&lt;String&gt; task;
    // Synchronized map access
    synchronized(map) {
        // If there is no task created for that instance of A, create it
        // and submit it for execution
        task = map.get(a);
        if (task == null) {
            task = createFutureTask(a); // TODO, but nothing too complicated
            // IMPORTANT! If you don't do this, the task is not executed
            // and .get() below will block indefinitely
            service.execute(task);
            map.put(a, task);
        }
    }
    // A FutureTask will keep its status! We can therefore call .get()
    // as much as we like; the computation will only have happened once
    return task.get();
}


One advantage is that if two instances created for A are equal (ie, the same a and b parameters), computation for c happens only once!