7

I have the following class:

public abstract class AbstractParent {
    static String method() {
        return "OriginalOutput";
    }
}

I want to mock this method. I decide to use JMockit. So I create a mock class:

public class MockParent {
    static String method() {
        return "MOCK";
    }
}

And my test code looks like this:

public class RealParentTest {

    @Before
    public void setUp() throws Exception {
        Mockit.redefineMethods( AbstractParent.class, MockParent.class );
    }


    @Test
    public void testMethod() {
        assertEquals(MockParent.method(),AbstractParent.method());
    }

}

Unfortunately this test says that AbstractParent returns "OriginalOutput" instead of "MOCK". Any ideas why? Am I doing something wrong? I've tried declaring my mock class as abstract as well, to no avail.

Edit Note that making the method public causes the test to run without a problem... this is weird because with JMockit you are supposed to be able to mock methods of any scope.

Answer Only the mock method needs to be public, you can leave the original method as is.

Epaga
  • 38,231
  • 58
  • 157
  • 245
  • Just for the passing googler..the accepted answer is now out of date as Mockit.redefineMethods is deprecated...I'm trying to find the correct. – Gareth Davis Dec 14 '10 at 13:06

2 Answers2

6

Found the solution: you simply need to make the mock's method public (the original method can stay in its original visibility).

I don't know why this works while the original way doesn't (someone who does is more than welcome to chime in), but all you need to do is simply change the mock class in the example above to:

public class MockParent {
    public static String method() {
        return "MOCK";
    }
}
Epaga
  • 38,231
  • 58
  • 157
  • 245
  • 1
    You don't even have to make it a static in the MockParent. – Cem Catikkas Oct 22 '08 at 15:05
  • 1
    jmockit looks at public methods only. This allows your mock implementation to have internal methods which don't correspond to methods in the source class – Kris Pruden Oct 23 '08 at 00:10
  • 2
    The reason why the mock method needs to be public is that JMockit modifies the mocked method to make a call to the mock method. That is, a call to the original method gets redirected from inside that same method to the mock. Therefore, the mock method must be accessible from that point where the call is inserted. – Rogério Jul 02 '09 at 01:01
4

Apparently the new way to do this is to use MockUp<T>

new MockUp<AbstractParent>(){
    @Mock String method() {
        return "MOCK";
    }
};

assertEquals("MOCK" AbstractParent.method());

Another alternative is apparently to continue with something like MockParent with a @MockClass annonation. Haven't done this myself as the another inline version does the job.

I've implemented this in an example project on github.

Gareth Davis
  • 27,701
  • 12
  • 73
  • 106
  • The original `AbstractParent.method()` is `static`. This way can't be taken for `static` methods. – Adeel Ansari Mar 16 '11 at 14:46
  • 3
    @Adeel I beg to differ https://github.com/gid79/q224721-jmockit-non-public-methods – Gareth Davis Mar 16 '11 at 21:10
  • Sorry for my earlier comment, actually I tried it but it was not really working, then I got to know that that was because of something completely different. +1 for providing the example. – Adeel Ansari Mar 17 '11 at 08:44