Mockito bypass static method for testing

后端 未结 3 1834
北海茫月
北海茫月 2020-12-17 16:15

I need to test handleIn() method using Mockito.

However the code need to call this legacy code Util.getContextPDO which is a static method.

Note that in test

相关标签:
3条回答
  • 2020-12-17 16:34

    Changed my testing to :

    @Test
    public void testHandleIn() throws Exception
    {
      IPDO pdo = new PDODummy();
    
    
      MyClass handler = new MyClass ();
      MyClass handler2 = spy(handler);
    
      doReturn(pdo ).when( handler2 ).getIPDO();
      PDOUtil.setPDO(pdo, LogicalFieldEnum.P_TX_CTGY, "test123");
      IPDO pdoNew = handler2.getIPDO();
    
      Assert.assertEquals("test123,(PDOUtil.getValueAsString(pdoNew, LogicalFieldEnum.P_TX_CTGY)));
    
    }
    

    Solved after reading Effective Mockito.

    0 讨论(0)
  • 2020-12-17 16:47
    when(handler2.getIPDO()).thenReturn(pdo);
    

    Will actually call the method and then return pdo regardless.

    Whereas:

    doReturn(pdo).when(handler2).getIPDO();
    

    Will return pdo without calling the getIPDO() method.

    0 讨论(0)
  • 2020-12-17 16:55

    A good technique for getting rid of static calls on 3rd party API is hiding the static call behind an interface.

    Let's say you make this interface :

    interface IPDOFacade {
    
        IPDO getContextPDO();
    }
    

    and have a default implementation that simply calls the static method on the 3rd party API :

    class IPDOFacadeImpl implements IPDOFacade {
    
        @Override
        public IPDO getContextPDO() {
            return Util.getContextPDO();
        }
    }
    

    Then it is simply a matter of injecting a dependency on the interface into MyClass and using the interface, rather than the 3rd party API directly :

    public class MyClass {
    
        private final IPDOFacade ipdoFacade;
    
        public MyClass(IPDOFacade ipdoFacade) {
            this.ipdoFacade = ipdoFacade;
        }
    
        public String handleIn(Object input) throws Throwable
        {
            String result = "";
            IPDO pdo = getIPDO();
    
            someImportantBusinessLogic(pdo);
    
            return result;
        }
    
        ...
    
    }
    

    In your unit test, you can then easily mock your own interface, stub it any way you like and inject it into the unit under test.

    This

    • avoids the need to make private methods package private.
    • makes your tests more readable by avoiding partial mocking.
    • applies inversion of control.
    • decouples your application from a specific 3rd party library.
    0 讨论(0)
提交回复
热议问题