Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
928 views
in Technique[技术] by (71.8m points)

java - powermockito: How to mock abstract method in enum

Consider the following (simplified) enumeration:

MyEnum {
    ONE public int myMethod() {
        // Some complex stuff
        return 1;
    },

    TWO public int myMethod() {
        // Some complex stuff
        return 2;
    };

    public abstract int myMethod();
}

This is used in a function like:

void consumer() {
    for (MyEnum n : MyEnum.values()) {
       n.myMethod();
    }
}

I'd now like to write a unit test for consumer that mocks out the calls to myMethod() in each of the enumeration instances. I've tried the following:

@RunWith(PowerMockRunner.class)
@PrepareForTest(MyEnum.class)
public class MyTestClass {
    @Test
    public void test() throws Exception {
        mockStatic(MyEnum.class);

        when(MyEnum.ONE.myMethod()).thenReturn(10);
        when(MyEnum.TWO.myMethod()).thenReturn(20);

        // Now call consumer()
}

But the real implementations of ONE.myMethod() and TWO.myMethod() are being called.

What have I done wrong?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
  1. Each constant in enum it's a static final nested class. So to mock it you have to pointe nested class in PrepareForTest.
  2. MyEnum.values() returns pre-initialised array, so it should be also mock in your case.
  3. Each Enum constant it is just public final static field.

All together:

@RunWith(PowerMockRunner.class)
@PrepareForTest(
value = MyEnum.class,
fullyQualifiedNames = {
                          "com.stackoverflow.q45414070.MyEnum$1",
                          "com.stackoverflow.q45414070.MyEnum$2"
})

public class MyTestClass {

  @Test
  public void should_return_sum_of_stubs() throws Exception {

    final MyEnum one = mock(MyEnum.ONE.getClass());
    final MyEnum two = mock(MyEnum.TWO.getClass());

    mockStatic(MyEnum.class);
    when(MyEnum.values()).thenReturn(new MyEnum[]{one, two});

    when(one.myMethod()).thenReturn(10);
    when(two.myMethod()).thenReturn(20);

    assertThat(new Consumer().consumer())
        .isEqualTo(30);
  }

  @Test
  public void should_return_stubs() {

    final MyEnum one = mock(MyEnum.ONE.getClass());

    when(one.myMethod()).thenReturn(10);

    Whitebox.setInternalState(MyEnum.class, "ONE", one);

    assertThat(MyEnum.ONE.myMethod()).isEqualTo(10);
  }

}

Full example


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...