Search code examples
javaunit-testingjunitmockitopowermockito

Mocked method is returning null instead of expected object


I have source code like below.

public class XYZClass {

    private static InitialContext ctx;

    private static InitialContext getCtx(){
        try{
            if(ctx == null)
                    ctx = new InitialContext();

        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return ctx;
    }
    public static IMFTPManagerService getIMFTPManagerFacade() {
        try {
            return (IMFTPManagerService) getCtx().lookup("abc");
        } catch (Exception e) {
            return null;
        }
    }
}

I am trying to write test case for getIMFTPManagerFacade() method. I need to mock getCtx() method which is private and static and also lookup("abc") method. So I did it in the below way. I am not getting any error or any exception in mocking. Also when I debug the line individual method return values, the getCtx() method is returning the mocked object and lookup() method is also returning the required mocked object. But after completing the execution of that entire line return (IMFTPManagerService) getCtx().lookup("abc");, the line returns null to the test class method. Can any one find me a solution? If my question is not clear, please ask.

And here is the test class:

 @RunWith(PowerMockRunner.class)
 @PrepareForTest(XYZClass.class)
 public class XYZClassTest {
    private InitialContext ctx;

    @Before
    public void setUp() throws Exception {
        PowerMockito.mockStatic(XYZClass.class);
        ctx = Mockito.spy(new InitialContext());
        PowerMockito.doReturn(ctx).when(XYZClass.class, "getCtx");

        IMFTPManagerBean service1 = new IMFTPManagerBean();
        Mockito.doReturn(service1).when(ctx).lookup(Mockito.eq("abc"));
    }


    @Test
    public void testGetIMFTPManagerFacade() {
        IMFTPManagerService service = XYZClass.getIMFTPManagerFacade();
        assertEquals(IMFTPManagerService.class, service.getClass());
    }
}

Solution

  • When you partially mock static methods of a class, you need to explicitely state if real implementation should be called (check thenCallRealMethod below).

    If you don't that, any method you call would be treated as a method on a mock without specified behaviour, and thus return null.

    On top of that:

    • you use EJBFacades which was not posted in the question. I've rewritten the test in terms of XYZClass
    • your assertion will fail, as you return a subclass of the service.
    package com.test.powermock.teststacitejb;
    
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.Mockito;
    import org.powermock.api.mockito.PowerMockito;
    import org.powermock.core.classloader.annotations.PrepareForTest;
    import org.powermock.modules.junit4.PowerMockRunner;
    
    import javax.naming.InitialContext;
    
    import static org.junit.Assert.assertTrue;
    
    @RunWith(PowerMockRunner.class)
    @PrepareForTest(XYZClass.class)
    public class XYZClassTest {
    
    
        private InitialContext ctx;
    
        @Before
        public void setUp() throws Exception {
            PowerMockito.mockStatic(XYZClass.class);
            ctx = Mockito.spy(new InitialContext());
            PowerMockito.doReturn(ctx).when(XYZClass.class, "getCtx");
    
            IMFTPManagerBean service1 = new IMFTPManagerBean();
            Mockito.doReturn(service1).when(ctx).lookup(Mockito.eq("abc"));
            PowerMockito.when(XYZClass.getIMFTPManagerFacade()).thenCallRealMethod();
        }
    
    
        @Test
        public void testGetIMFTPManagerFacade() {
            IMFTPManagerService service = XYZClass.getIMFTPManagerFacade();
            assertTrue(service instanceof IMFTPManagerService);
        }
    }