-1

Version of JMockit that was used: 1.21 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");
    };
}

I try to verify calling method by fake an interfacein this tutorial. http://jmockit.org/tutorial/Faking.html#interfacesd

Test method.

public class TestInterfaceTest {
    TestClass sut;
    @Before
    public void setUp() {
        sut = Deencapsulation.newInstance(TestClass.class);
    }
    @Test
    public void mockAllClassesImplementingAnInterface() {

        TestInterface testInterface = new MockUp<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

If you guys don't mind, could you please tell me how to resolve this byg. Many thanks.

Long Nguyen
  • 9,898
  • 5
  • 53
  • 52
  • Once I fixed the errors in your "sample code" (*please* make sure your [MCVE](http://stackoverflow.com/help/mcve) compiles and runs!), everything worked fine and I did not see this error. You'll have to elaborate on your problem. – dcsohl Dec 05 '16 at 17:00
  • Thanks @dcsohl for your confirm. Current , I'm implementing on version 1.21, it will throw that error. Not only version 1.21, but version 1.29 also throws that exception. :D What version did you use to reproduce my error? – Long Nguyen Dec 06 '16 at 04:29
  • I test on Android Studio :D – Long Nguyen Dec 06 '16 at 05:51

2 Answers2

2

Your problem, in my reevaluation of this issue, would seem to lie in the line inv.proceed(). You can't have that line in a Mockup of an interface.

Invocation.proceed() is intended when you want the MockUp implementation to proceed into the real code. But because you are mocking up an interface, there is no real code. You may think there is because your implementation of TestClass has an anonymous implementation of the interface, but the MockUp knows nothing of that anonymous class; it's doing a mockup of the interface and not of your anonymous implementation.

If you get rid of that line, the call to Invocation.proceed(), I think you'll find your error goes away.

dcsohl
  • 7,186
  • 1
  • 26
  • 44
  • Thanks for your kind helping. So we have no idea to verify an anonymous method? – Long Nguyen Dec 07 '16 at 18:35
  • I didn't say that. I said you couldn't proceed into it. You can mock it and verify it's being called, though. – dcsohl Dec 07 '16 at 19:14
  • I mean that we couldn't process into that class and verify that subMehod was called inside actual method. Is that right? Many thanks for kind support. – Long Nguyen Dec 08 '16 at 01:57
  • It all depends on what you *really* want to test. You can't mock up the anonymous class or actually test that it gets called ... but you *can* quite easily verify that it does what it's supposed to. In this case, you can verify that `subMethod()` gets called. You will have to do this with [partial mocking](http://jmockit.org/tutorial/Mocking.html#partial) of `sut`, and you should question whether you really want to do this, but you definitely can. – dcsohl Dec 08 '16 at 16:37
  • Thanks you so much. I didn't expect that it's as simple as that. I often use partial mocking of sut to verify. You save my life. Thanks you again. I will describe code which works for me in below. – Long Nguyen Dec 11 '16 at 19:00
-1

Based on the guidance of @dcsohl. The code below works for me.

    @Test
    public void mockAllClassesImplementingAnInterface() {
        // Partial mocking
        new NonStrictExpectations(sut) {
            {
                sut.subMethod();
            }
        };

        // Actual invocation
        Deencapsulation.invoke(Deencapsulation.getField(sut, "inner"), "callMethod");
        // Verify
        new Verifications() {
            {
                Deencapsulation.invoke(sut, "subMethod");
                times = 1;
            }
        };
    }
Long Nguyen
  • 9,898
  • 5
  • 53
  • 52
  • I am afraid this test is full of mistakes (should not use `Deencapsulation.invoke`, for one). But more important, the whole thing (test + code to be tested) seems meaningless... A proper test is supposed to verify some meaningful and externally observable behavior. – Rogério Dec 13 '16 at 16:20