简体   繁体   中英

Mocking getResource in static block with PowerMock

How to mock getResourceAsStream in the static block ? I think it is untestable.

I reviewed SO and cannot find the answer. The closes-SO-post-here does not address the issue as the call to getResourceAsAStream in the post is not from a static block .

I tried PowerMock, and run into number of limitations. First if I want to mock SomeProperties.class.getResourceAsStream - the static block will execute, as I will need to refer to the class itself. I can suppress static block to prevent doing so, but this will prevent me from getting the static block to execute at all. The solution would be to postpone the execution of the static block until after someProperties.class.getResourceAsStream is mocked. I do not think it is possible though. It seems that this code is purely untestable; Any other ideas?

Here is the code [and a link to GITHUB] :

package com.sopowermock1;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class SomeProperties {

    private static Properties props = new Properties();

    static {
        InputStream is = SomeProperties.class.getResourceAsStream("/some.properties");

        try {
            props.load(is);
            System.out.println("Properties.props.keySet() = " + props.keySet());            
        } catch (IOException e) {
            // How test this branch???
            System.out.println("Yes. We got here.");
            throw new RuntimeException(e);
        }
    }

    private SomeProperties() {}; // to makes life even harder...

    public static String getVersion() {
        return props.getProperty("version");
    }
}

And here is the test GITHUB Link

package com.sopowermock1;
import java.io.InputStream;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import com.sopowermock1.SomeProperties;

@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeProperties.class)

// This will prevent running static block completely:
// @SuppressStaticInitializationFor("com.sopowermock1.SomeProperties")
public class SomePropertiesTest {

    @Mock
    private static InputStream streamMock;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(SomeProperties.class);
        System.out.println("test setUp");
    }

    @Test(expected = RuntimeException.class)
    public void testStaticBlock() {

        PowerMockito.mockStatic(SomeProperties.class); // this will mock all static methods (unwanted as we want to call getVersion)

        // This will cause static block to be called.
        PowerMockito.when(SomeProperties.class.getResourceAsStream("/some.properties")).thenReturn(streamMock);
        SomeProperties.getVersion();
    }
}

Any ideas?. Full GITHUB source is here .

as mention in How to mock getResourceAsStream method using PowerMockito and JUnit? , use Extract Delegate , then mock the delegate class such as XXStreamFetcher , and then you can test it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM