javamockingpowermock

mock throw exception and new object seems not to be working using powermock


I have following simple test case that use powermock to mock throw exception from the method of ExceptionClass.getRandom by mocking the creation of Random object.

But, from the test result, it looks that obj.getRandom() returns random value so that Assert.assertTrue(obj.getRandom() == 111) fails, but I think obj.getRandom() should return 111 with the effort of mocking Random creation and throwing exception.

package com.example;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.powermock.modules.junit4.PowerMockRunner;

import static org.powermock.api.mockito.PowerMockito.*;

import java.util.Random;

class ExceptionClass {
    public int getRandom() {
        try {
            //Mock the random object using whenNew(Random.class).withNoArguments()
            Random random = new Random();
            //random.nextInt should throw IllegalStateException,so that 111 is returned
            return random.nextInt();
        } catch (Exception e) {
            return 111;
        }
    }
}

@RunWith(PowerMockRunner.class)
public class MockThrowExceptionTest {
    @InjectMocks
    ExceptionClass obj;

    @Test
    public void testGetRandom() throws Exception {
        Random rand = mock(Random.class);
        whenNew(Random.class).withNoArguments().thenReturn(rand);
        when(rand.nextInt()).thenThrow(new IllegalStateException());

        //An exception is thrown in ExceptionClass.getRandom method, so that 111 should be returned,but it is a random value
        Assert.assertTrue(obj.getRandom() == 111);
    }

}

Solution

  • You can mock constructor using mockito-inline.

    Required dependency

        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-inline</artifactId>
            <version>5.2.0</version>
            <scope>test</scope>
        </dependency>
    

    Here is an example of usage

    @Test
    public void testGetRandom() throws Exception {
        try (var m = mockConstruction(Random.class,
            (mock, context) -> {
                when(mock.nextInt()).thenReturn(111);
            })) {
            Random r = new Random();
            assertEquals(111, r.nextInt());
        }
    }