Search code examples
junit4jmockitmethod-chaining

JMockit Cascading and Interfaces


I am trying to mock the following chain of method calls which are called from my ClassUnderTest.methodUnderTest:

((AService) System.getService(AService.NAME)).isA();

where the System.getService static method is declared to return a Service interface, but returns a concrete subclass based on the passed string parameter. isA() is a method on the AService subclass and does not exist on the Service interface, hence requiring the cast.

I am using JMockit (1.8) and have attempted to mock the call chain as follows

public class TestCascadingMock {

    @Test
    public void testMethodUnderTest(@Cascading System system) {
        new Expectations(system) {{
            ((AService) System.getService(AService.NAME)).isA();
            result = false;
        }};

        ClassUnderTest c = new ClassUnderTest();
        boolean isA = c.methodUnderTest();
        assertFalse(isA);
    }

}

This is resulting in a ClassCastException

java.lang.ClassCastException: org.gwl.test.$Impl_Service cannot be cast to org.gwl.test.AService
    at org.gwl.test.TestCascadingMock$1.<init>(TestCascadingMock.java:14)
    at org.gwl.test.TestCascadingMock.testMethodUnderTest(TestCascadingMock.java:13)

I can understand what the excpetion is telling me - JMockit can only return a mocked implementation of Service, not AService - but how do I specify that I always wish this call to return false?

Thanks in advance.


Solution

  • Write the test as follows:

    @Test
    public void testMethodUnderTest(
        @Mocked System system, @Mocked final AService aService)
    {
        new NonStrictExpectations() {{
            System.getService(AService.NAME); result = aService;
            aService.isA(); result = false;
        }};
    
        ClassUnderTest c = new ClassUnderTest();
        boolean isA = c.methodUnderTest();
        assertFalse(isA);
    }
    

    Note that the aService.isA() expectation can be removed, if desired, since false is the default value for methods returning boolean.