trunkc
trunkc

Reputation: 6293

JMockit mocking System.currentTimeMillis()

Running this test:

@Test
public void testSystemCurrentTimeMillis() {
    new NonStrictExpectations(System.class) {{
        System.currentTimeMillis(); result = 1438357206679L;
    }};
    long currentTime = System.currentTimeMillis();
    assertEquals(1438357206679L, currentTime);
}

I get an IllegalStateException:

java.lang.IllegalStateException: Missing invocation to mocked type at this point; please make sure such invocations appear only after the declaration of a suitable mock field or parameter
    at unittests.DateTest$1.(DateTest.java:24)
    at unittests.DateTest.testSystemCurrentTimeMillis(DateTest.java:23)

What's wrong with my Test (JMockit 1.18)?

Upvotes: 3

Views: 11229

Answers (5)

Milan
Milan

Reputation: 1750

I use PowerMock for this:

private void configureSystemClockMock(final int clockJump) {
    AtomicInteger callCount = new AtomicInteger();

    Answer<Integer> answer = invocation -> {
        callCount.addAndGet(1);
        return callCount.get() * clockJump;
    };

    PowerMockito.mockStatic(System.class);
    PowerMockito.doAnswer(answer).when(System.class);
    System.currentTimeMillis();
}

Of course you put whatever you wish in the invocation.

Upvotes: 0

Amruta Mistry
Amruta Mistry

Reputation: 69

Yeah this is partial mocking. With small correction in the nonStrictExpectation(){} your above mentioned code can also get fix:

@Mocked
private System system;

new NonStrictExpectations() {{
    System.currentTimeMillis(); 
    result = 1438357206679L;
}};

long currentTime = System.currentTimeMillis();
assertEquals(1438357206679L, currentTime);

This should also work.

Upvotes: 0

trunkc
trunkc

Reputation: 6293

My final solution is to create a MockUp for System, that only mocks the method currentTimeMillis():

private static class SystemMock extends MockUp<System> {
    @Mock
    public static long currentTimeMillis() {
        return 10000000L;
    }
}

@Test
public void testAddNowDate() {
    new SystemMock();
    long currentTime = System.currentTimeMillis();
    assertEquals(10000000L, currentTime);
}

Upvotes: 3

Amruta Mistry
Amruta Mistry

Reputation: 69

This thing has been introduced in JMockit version 1.17 only to use object reference with your NonStrictExpectation(){} block,Deprecated attribute value for Mocked

Deprecated the "value" attribute of @Mocked, which is used for "static" partial mocking. Existing uses should be replaced with "dynamic" partial mocking, by passing the instance or class to partially mock in a call to the Expectations(Object...) constructor, or by applying a MockUp class.

Please refer the below link: JMockit version history

Upvotes: 1

unigeek
unigeek

Reputation: 2826

Like so many things with JMockit, it's easy enough to do. Try this..

@Test
public void testSystemCurrentTimeMillis(@Mocked final System unused) {
    new NonStrictExpectations() {{
        System.currentTimeMillis(); result = 1438357206679L;
    }};
    long currentTime = System.currentTimeMillis();
    assertEquals(1438357206679L, currentTime);
}

Found this site to be an excellent reference, by the way. Probably you were tripped up by the static method. All you need to do is declare the class with the static method as mocked--you never need to refer to the variable, hence I named it "unused".

Upvotes: 2

Related Questions