4

I have class which uses @PostConstruct to cache some objects.

@Component
public class A {

   @Autowired
   private B b;

   private X x;

   @PostConstruct 
   public void init(){
       x = b.doSomething()
   }

}

public class C {

   @Autowired
   private A; 
}


public class TestClass {

   @Autowired
   private A;

   @Before
   public init() {
       expect(b.dosomething()).andReturns(x);
   }

   @Test
   public test1() {
       //test
   }
}

I have mocked B since it makes an HTTP call to get x. But while running this through unit test, I'm getting following error:

Missing behaviour definition for the preceding method call:
B.dosomething().andXXX() 

Everything works fine if I do the same thing inside some normal method of class A. I'm using spring for dependency injection.

I think the reason for this behaviour is, since I'm setting expectation on mock of class B inside my unit test which is invoked 'after' this init method is invoked. How can I test this ?

Gaetan
  • 2,802
  • 2
  • 21
  • 26
Deepikaa
  • 61
  • 6
  • Show us your code. We can't explain why code doesn't work without seeing the code. – JB Nizet Aug 10 '14 at 18:18
  • I think I can sense what the problem is going to be, but is it possible you could provide your test class and test context so that we can see the code where the issue is occurring? – Dan Temple Aug 11 '14 at 07:52
  • Seeing the test context would also be helpful, but ultimately your issue is that you're not injecting the instance of B into your test class. Without a reference to the actual instance of B that is injected into the A object, you won't be able to set expectations on it. (Keep in mind, objects within Spring contexts are singletons.) Once you have the reference in your test class, you'll likely hit the issue you're thinking of. I'd recommend creating your mock B instance in a static method that sets the expectation and puts the mock into replay mode. – Dan Temple Aug 12 '14 at 07:43

1 Answers1

0

If you are looking to test the code in the @PostConstruct annotated "init" method of class A, you can consider testing it without using Spring in your test. You will need to inject dependencies manually.

One way to do it would be:

import org.easymock.EasyMock;
import org.junit.Before;
import org.junit.Test;
import org.powermock.reflect.Whitebox;

public class TestA {

    private A a = new A();
    private B b = EasyMock.createMock(B.class);

    @Before
    public void init() {
        Whitebox.setInternalState(a, "b", b);
    }

    @Test
    public void testInit() {
        EasyMock.reset(b);
        //define mock behavior here
        EasyMock.replay(b);

        a.init();

        //assert and verify
        EasyMock.verify(b);
    }
}
Varun Phadnis
  • 671
  • 4
  • 6