4

I am trying to verify a method call made by an indirect private field object. For example

Code to Test:

class A
{
    final private B b;
    public A(C c, D d)
    {
        this.b = new B(c,d);   
    }

    public void methodToTest()
    {
        b.wantToVerifyThisIsCalled();
    }
}

class B
{
   private C c;
   private D d;

   public B(C c, D d)
   {
      this.c = c; 
      this.d = d;
   }
   ...
   public void wantToVerifyThisIsCalled()
   {
       //do stuff 
       return;
   }
}

I want to verify that b.wantToVerifyThisIsCalled() method was called when I run A.methodToTest();

I tried something like this but this doesn't work:

C c = mock(C.class);
D d = mock(D.class); 
A a = new A(C,D);
B b = moc(B.class);

a.methodToTest();
verify(b).wantToVerifyThisIsCalled();  \\<-- This gives me error, wanted but not invoked

How should I verify that this b field object of class A is indeed making that method call ?

There is sadly no setter method and the field object is also marked as final :(

Thank you

user3808203
  • 153
  • 2
  • 12
  • 1
    In this case, the use of B is a private implementation detail and shouldn't be tested. Instead, test the calls on C and D. – chrylis -cautiouslyoptimistic- Jul 06 '14 at 18:24
  • possible duplicate of [What's the proper way to test a class with private methods using JUnit?](http://stackoverflow.com/questions/34571/whats-the-proper-way-to-test-a-class-with-private-methods-using-junit) – Raedwald Jul 06 '14 at 19:22

1 Answers1

3

That is happening because the B class object on which wantToVerifyThisIsCalled() method is invoked is not your mocked object. You should rather inject the mock object to A.

It would be better if your A class constructor directly takes a B instance rather than C and D, and relying on it to create B class object.

Try modifying your classes as such:

class A {
    private final B b;
    public A(B b) { this.b = b; }

    public void methodToTest() {
        b.wantToVerifyThisIsCalled();
    }
}

class B {
    private final C c;
    private final D d;
    public B(C c, D d) { this.c = c; this.d = d; }

    public void wantToVerifyThisIsCalled() { ... }
}

And then test it like this:

C c = mock(C.class);
D d = mock(D.class); 
B b = mock(B.class);// Find a way to set private fields (May be provide setters).
A a = new A(b);

a.methodToTest();
verify(b).wantToVerifyThisIsCalled();
Rohit Jain
  • 209,639
  • 45
  • 409
  • 525