简体   繁体   中英

PowerMockito mocking static class INSIDE enum?

I have a enum that has to have a inner static class for bean injection.

I feel I'm facing the most difficult situation for a mock: enum, static class, static field, static method..

public enum Category{

    C1(Something(Constants.getFactory().createSomething(""))),
    C2(...);

    public static Constants {
        @Autowired
        private static Factory factory;

        public static Factory getFactory(){
            return factory;
        }
    }
}

And my testing class using PowerMockito is:

@RunWith(PowerMockRunner.class)
@PrepareForTest({Category.class,Category.Constants.class})
public class CategoryTests {

    @Before
    public void setUp() throws Exception {
        PowerMockito.mockStatic(Category.class);
        PowerMockito.mockStatic(Category.Constants.class);  

        //This simply testing mock didn't work             
        //PowerMockito.when(Category.Constants
        //                .getFactory()).thenReturn("123");


        //I tried to mock the inner field 'factory' and use it directly without a getter 
        //(with small changes in the original class)
        //But it didn't work either
        Factory factory = PowerMockito.mock(Factory.class);
        NewClass newClass = PowerMockito.mock(NewClass.class);
        PowerMockito.when(Factory.createSomething(anySring()))
                                         .thenReturn(newClass);

        Whitebox.setInternalState(
                 Category.Constants.class,"factory",Factory);


        //This is like the most common way to stub
        //It didn't work, so I believe the inner static class were never mocked
        PowerMockito.doReturn(factory).when(Category.Constants.class,
                                       "getFactory", anyString());
    }


    //I don't know if real test cases matter that much but I update to add it for reference.
    @Test(dataProvider = "Case1")
    public void testFromFilterType(final String testName, String input, final Category expected) {
        assertEquals(Category.doSomething(input), expected);
    }

    @DataProvider(name = "Case1")
    Object[][] fromFilterTypeCases() {
        return new Object[][] {
            { "C1", "input1", Category.C1 },
            { "C2", "input2", Category.C2 },
        };
    }
}
//Currently the tests got skipped because in class Category Constants.getFactory().createSomething(""), 
//where Constants.getFactory() returns null and mocking doesn't work.

At first I didn't mock the Enum, but just the static inner class. After heavily searching, I tried in all ways. The setup seems correct but it may miss some tricks. Any helps?

A bit of guessing: Category.class is the class you intend to test. That class itself contains nothing that should require mocking/preparation. So: drop these parts in your code. Even if it doesn't cause your current issue, I am pretty sure that it might have all kinds of unwanted consequences when you start testing things later on.

Beyond that, the real answer would be to avoid the necessity for PowerMock(ito) in the very first place. You are already using @Autowired, which implies that you are using a DI framework. Most DI frameworks also have hooks for unit testing. So you should rather try to get @Autowired to work in your test setup.

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