jmockit / jmockit1

Advanced Java library for integration testing, mocking, faking, and code coverage
Other
465 stars 240 forks source link

How to call method of interface field #362

Closed zcmgyu closed 7 years ago

zcmgyu commented 7 years ago

I have interface like this. TestInterface:

public interface TestInterface {
    boolean callMethod();
}

A TestClass have field is a instance of that interface TestClass:

public class TestClass {
    private final TestInterface inner = new TestInterface() {
        @Override
        public boolean callMethod() {
            subMethod();
            return false;
        }
    };
        public void subMethod() { System.out.println("Sub method");
    };
}

This test case manages to verify call method subMethod from that field/ TestInterfaceTest:

public class TestInterfaceTest {
    @Mocked TestClass sut;
    @Test
    public void mockAllClassesImplementingAnInterface(@Mocked final TestInterface testInterface) {
        Deencapsulation.setField(sut, "inner", testInterface);
        // what we expect to be invoked
        new NonStrictExpectations() {
            {
                Deencapsulation.invoke(sut, "subMethod");
            }
        };
        // Actual invoke
        Deencapsulation.invoke(Deencapsulation.getField(sut, "inner"), "callMethod");
       // verify that we did invoke the expected method of collaborator
        new Verifications() {
            {
                Deencapsulation.invoke(sut, "subMethod"); times = 1;
            }
        };
   }
}

This is result:

mockit.internal.MissingInvocation: Missing 1 invocation to: helloandroid.examples.helloandroid.TestClass#subMethod() on mock instance: helloandroid.examples.helloandroid.TestClass@e50a6f6

I think that issue here is that Deencapsulation.invoke(Deencapsulation.getField(sut, "inner"), "callMethod") call to this method TestInterface#callMethod(). So, can't verify that i did invoke to subMethod() method


Could you give me some ideas to resolve this problem. Thanks you.

rliesenfeld commented 7 years ago

You can find information and example tests for cases like this in the JMockit Tutorial .

zcmgyu commented 7 years ago

Thanks for response from you @rliesenfeld. I'm sorry to bother you, could I ask you something more. I also tried your suggestion but I've received another exception like below:

Test method

public class TestInterfaceTest {
    @Mocked TestClass sut;
    @Test
    public void mockAllClassesImplementingAnInterface() {

        TestInterface testInterface = new MockTestInterface<TestInterface>() {
            @Mock
            public boolean callMethod(Invocation inv) {
                inv.proceed(); // throw exception here -> Will my expected method  be called here?
                return true;
            }
        }.getMockInstance();

        Deencapsulation.setField(sut, "INTER", testInterface);

        new NonStrictExpectations() {
            {
                Deencapsulation.invoke(sut, "subMethod");
            }
        };

        Boolean result = Deencapsulation.invoke(Deencapsulation.getField(sut, "INTER"), "callMethod");

        assertTrue(result);

        new Verifications() {
            {
                Deencapsulation.invoke(sut, "subMethod"); times = 1;
            }
        };
    }
}

java.lang.IllegalArgumentException: No class with name "ndroid.examples.helloandroid.$Impl_TestInterface" found

Thanks a lot