Mocking private method of class under test using JMockit

后端 未结 3 1009
醉话见心
醉话见心 2020-12-15 23:17

I want to mock private method of a class under test but method return false first two times when the method is called after that it should return false. Here is the code wha

相关标签:
3条回答
  • 2020-12-16 00:13

    This works for me:-

            new MockUp<ClassToTest>() {
                @Mock
                boolean methodToMock(int value) {
                    return true;
                }
            };
    
    0 讨论(0)
  • 2020-12-16 00:15

    Here, you can over-ride a particular method of the testing class with mock behavior.

    For the below code:

    public class ClassToTest 
    {
        public void methodToTest()
        {
            Integer integerInstance = new Integer(0);
            boolean returnValue= methodToMock(integerInstance);
            if(returnValue)
            {
                System.out.println("methodToMock returned true");
            }
            else
            {
                System.out.println("methodToMock returned true");
            }
            System.out.println();
        }
        private boolean methodToMock(int value)
        {
            return true;
        }
    }
    

    Test class would be:

    public class ClassToTestTest{
    
        @Test
        public void testMethodToTest(){
    
            new Mockup<ClassToTest>(){
                @Mock
                private boolean methodToMock(int value){
                    return true;
                }
            };
    
            ....    
    
        }
    }
    
    0 讨论(0)
  • 2020-12-16 00:19

    Using Expectations (or StrictExpectations)

    Using a combination of Expectations and Deencapsulation.invoke(), you can partially mock the tested object:

    import org.junit.Test;
    import static mockit.Deencapsulation.*;
    import mockit.*;
    
    public class TestAClass
    {
        public static class ClassToTest 
        {
            public void methodToTest()
            {
                boolean returnValue = methodToMock(0);
                System.out.println("methodToMock returned " + returnValue);
            }
    
            private boolean methodToMock(int value) { return true; }
        }
    
        @Tested ClassToTest classToTestInstance;
    
        @Test
        public void partiallyMockTestedClass() {
            new Expectations(classToTestInstance) {{
                invoke(classToTestInstance, "methodToMock", anyInt);
                result = false;
                times = 2;
            }};
    
            classToTestInstance.methodToTest();
            classToTestInstance.methodToTest();
            classToTestInstance.methodToTest();
        }
    }
    

    The test above prints:

    methodToMock returned false
    methodToMock returned false
    methodToMock returned true
    

    In general, of course, we should avoid mocking private methods. That said, I have found in practice that it is sometimes useful to do so, typically when you have a private method which does something non-trivial and was already tested by another test; in such a case, mocking that private method in a second test (either for a different public method or a different path through the same public method) may be significantly easier than setting up necessary inputs/conditions.

    Using NonStrictExpectations (deprecated in JMockit 1.23)

    It's just as easy to write the test with a NonStrictExpectations (the original attempt by the OP didn't work only because the same non-strict expectation was recorded twice, with the second recording overriding the first):

    @Test
    public void partiallyMockTestedClass() {
        new NonStrictExpectations(classToTestInstance) {{
            invoke(classToTestInstance, "methodToMock", anyInt);
            returns(false, false, true);
        }};
    
        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();
    }
    

    Use a Delegate

    If more flexibility is needed, we can always record a Delegate-based result:

    @Test
    public void partiallyMockTestedClass() {
        new NonStrictExpectations(classToTestInstance) {{
            invoke(classToTestInstance, "methodToMock", anyInt);
    
            result = new Delegate() {
               boolean delegate() {
                   boolean nextValue = ...choose next return value somehow...
                   return nextValue;
               }
            }
        }};
    
        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();
        classToTestInstance.methodToTest();
    }
    
    0 讨论(0)
提交回复
热议问题