Lonnie Lewis
Lonnie Lewis

Reputation: 65

Powermock, mockStatic of UUID.getRandom works in test class but doesn't in the class tested

Strange case: using Powermock to mock out UUID.getRandom(). This works within the JUnit test class but when the class under test (a Filter, if that matters) calls UUID.getRandom, a unique UUID is produced.

Simple test case

@RunWith(PowerMockRunner.class)
@PrepareForTest({UUID.class})
public class MyTest {

    private MyFilter filter;

    @Before
    public void setup() {

        //The most convenient way to get a UUID, have also tried creating one manually
        UUID uuid = UUID.randomUUID();

        mockStatic(UUID.class);

        PowerMockito.when(UUID.randomUUID()).thenReturn(uuid);

        filter = new MyFilter();
    }

    @Test
    public void testMyUUID() {

        //This test works
        assertEquals(UUID.randomUUID(), UUID.randomUUID());

    }

    @Test
    public void testFilterUUID() {

        //This test fails
        assertEquals(UUID.randomUUID(), filter.getUUID());
    }
}

Simple class being tested

public class MyFilter implements Filter {

    public UUID getUUID() {

        return UUID.randomUUID();
    }
}

Pretty simple stuff, have done mocking like this before, just can't figure out why this case doesn't work.

Using Powermock version 1.5.

Upvotes: 0

Views: 1275

Answers (2)

Amirsalar
Amirsalar

Reputation: 729

The accepted solution that is mentioned here won't work if you have multiple tests that tries to mockStatic before the tests, since mockStatic method from Mockito does not automatically close after the test.

I wrote the below solution which handles multiple tests by using PowerMockito.mockStatic instead of Mockito.mockStatic:


@RunWith(PowerMockRunner.class)
@PrepareForTest({MyFilter.class, UUID.class})
@PowerMockIgnore({"com.sun.org.apache.xerces.*", "javax.xml.*", "org.xml.*", "javax.management.*"})
public class MyTest {

    @Before
    public void setup() {
        UUID uuid = UUID.randomUUID();
        PowerMockito.mockStatic(UUID.class);
        PowerMockito.when(UUID.randomUUID()).thenAnswer((invocation) -> uuid);

        filter = new MyFilter();
    }

    @Test
    public void testMyUUID() {
        //This test works
        assertEquals(UUID.randomUUID(), UUID.randomUUID());

    }

    @Test
    public void testFilterUUID() {
        //This test fails
        assertEquals(UUID.randomUUID(), filter.getUUID());
    }
}

NOTE to how mockStatic is used from PowerMockito library not the Mockito.

Upvotes: 1

Morfic
Morfic

Reputation: 15518

I believe UUID falls under the "system classes" category, so you need to prepare for test the class calling UUID.randomUUID()(related github issue)., thus changing to @PrepareForTest({MyFilter.class}) should fix things. The following works as expected with JUnit 4.4 & Powermock 1.5, as well as JUnit 4.12 and Powermock 1.7.3:

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyFilter.class)
public class MyTest {

    private MyFilter filter;

    @Before
    public void setup() {
        //The most convenient way to get a UUID, have also tried creating one manually
        UUID uuid = UUID.randomUUID();
        mockStatic(UUID.class);
        PowerMockito.when(UUID.randomUUID()).thenReturn(uuid);
        filter = new MyFilter();
    }

    @Test
    public void testMyUUID() {
        //This test works
        assertEquals(UUID.randomUUID(), UUID.randomUUID());

    }

    @Test
    public void testFilterUUID() {
        //This test fails
        assertEquals(UUID.randomUUID(), filter.getUUID());
    }
}

Upvotes: 1

Related Questions