如何模拟私有静态 属性,特别是针对 ResourceBundle

How to mock a private static property, specially for ResourceBundle

我想模拟失踪时的情况message.properties

public class ClassToTest{
    private static ResourceBundle bundle = ResourceBundle.getBundle("message");
    public static String getMessage(String key){
        return bundle.getString(key);
    }
}

但是当我尝试时:

@RunWith(PowerMockRunner.class)
@PrepareForTest(ResourceBundle.class)
public class ClassToTestTest{

    @Test
    public void myTest(){
        PowerMockito.spy(ResourceBundle.class);
        PowerMockito.when(ResourceBundle.class, "getBundle").thenThrow(new Exception("missing message.properties"));
    }

}

我也尝试过其他方法,但我总是得到 NoClassDefFoundError:org/mockito/exceptions/Reporter

我会选择以下内容(注意 - Mockito 3.4.x 需要模拟静态方法)

public class ClassToTestTest {
    @Test
    public void test() {
        try (MockedStatic<ResourceBundle> dummyStatic = Mockito.mockStatic(ResourceBundle.class)) {
            dummyStatic.when(() -> ResourceBundle.getBundle(anyString()))
                       .thenThrow(new MissingResourceException("s", "className", "key"));
            // when
            try {
                var underTest = new ClassToTest();
            } catch (ExceptionInInitializerError ex) {
                var cause = ex.getCause();
                Assertions.assertEquals(MissingResourceException.class, cause);
            }
        }
    }
}

与 PowerMock 相同的测试:

import org.junit.Assert;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.junit.Test;

import java.util.MissingResourceException;
import java.util.ResourceBundle;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassToTest.class})
public class ClassToTestTest {
    @Test
    public void myTest() {
        var exMessage = "m1";
        try {
            PowerMockito.mockStatic(ResourceBundle.class);
            PowerMockito.when(ResourceBundle.getBundle("message"))
                        .thenThrow(new MissingResourceException(exMessage, "className", "key"));
            var underTest = new ClassToTest();
        } catch (ExceptionInInitializerError ex) {
            Assert.assertEquals(MissingResourceException.class, ex.getCause().getClass());
            Assert.assertEquals(exMessage, ex.getCause().getMessage());
        }
    }
}