Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

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

java - How to mock an enum singleton class using Mockito/Powermock?

I am unsure on how to mock an enum singleton class.

public enum SingletonObject{
  INSTANCE;
  private int num;

  protected setNum(int num) {
    this.num = num;
  }

  public int getNum() {
    return num;
  }

I'd like to stub getNum() in the above example, but I can't figure out how to mock the actual SingletonObject class. I thought using Powermock to prepare the test would help since enums are inherently final.

//... rest of test code
@Test
public void test() {
  PowerMockito.mock(SingletonObject.class);
  when(SingletonObject.INSTANCE.getNum()).thenReturn(1); //does not work
}

This is using PowerMockMockito 1.4.10 and Mockito 1.8.5.

See Question&Answers more detail:os

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

2 Answers

0 votes
by (71.8m points)

If you want to stub out what INSTANCE returns, you can do it but it's kind of nasty (using reflection & bytecode manipulation). I created & tested a simple project with three classes using the PowerMock 1.4.12 / Mockito 1.9.0. All classes were in the same package.

SingletonObject.java

public enum SingletonObject {
    INSTANCE;
    private int num;

    protected void setNum(int num) {
        this.num = num;
    }

    public int getNum() {
        return num;
    }
}

SingletonConsumer.java

public class SingletonConsumer {
    public String consumeSingletonObject() {
        return String.valueOf(SingletonObject.INSTANCE.getNum());
    }
}

SingletonConsumerTest.java

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

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

@RunWith(PowerMockRunner.class)
@PrepareForTest({SingletonObject.class})
public class SingletonConsumerTest {
    @Test
    public void testConsumeSingletonObject() throws Exception {
        SingletonObject mockInstance = mock(SingletonObject.class);
        Whitebox.setInternalState(SingletonObject.class, "INSTANCE", mockInstance);

        when(mockInstance.getNum()).thenReturn(42);

        assertEquals("42", new SingletonConsumer().consumeSingletonObject());
    }
}

The call to the Whitebox.setInternalState replaces INSTANCE with a mock object that you can manipulate within your test.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
0 votes
by (100 points)

You can directly mock an enum using Mockito 2. But you will have to activate the extension. Check this resource for the steps.

Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...