0

I have a dependency on an enum singleton class like

public enum SingletonObject {
  INSTANCE;
  
  SingletonObject() {
    // some annoying initialization
  }

  public callDB() {
    this.num = num;
  }

}

I am trying to test a class like

public class MyClass {
  public void doSomething() {
    // some code
    SingletonObject.INSTANCE.callDB();
  }
}

Following this answer, I've tried simply testing the mock with the following code, but I seem to be running into problems with the enum calling its constructor

public class MyClassTest {
    @Mocked
    private SingletonObject singleton;
    
    @Before
    public void setup() {
        Deencapsulation.setField(SingletonObject.class, "INSTANCE", singleton);
    }
    
    @Test
    public void test() {
        assertSame(singleton, SingletonObject.INSTANCE);
    }
}

Using an interface seems somewhat promising, but I question whether that is the best way of going about this problem.

It looks like PowerMockito is promising as well, but I would like to save that as a last resort for various reasons.

So how can I mock this enum singleton without invoking its constructor?

Azianese
  • 554
  • 7
  • 21

1 Answers1

0

Try something like this. This creates a partial-mock of 'MyClass' and a Mock SingletonObject, calls the (real) doSomething method of MyClass, and confirms that the (mock) callDB() method of SingletonObject is invoked by it precisely once.

@Test
public void testdoSomething(
    @Mocked final SingletonObject singleton)
{
    final MyClass clz = new MyClass();

    new Expectations(clz)
    {
        {
            SingletonObject.INSTANCE.callDB();
            times = 1;
        }
    };
    clz.doSomething();
}
Jeff Bennett
  • 996
  • 7
  • 18
  • I get the following error when trying this: java.lang.InternalError: class redefinition failed: invalid class at sun.instrument.InstrumentationImpl.retransformClasses0(Native Method) – Azianese Jul 08 '20 at 04:29