Как издеваться над enum singleton с помощью jmockit?

У меня есть зависимость от одноэлементного класса перечисления, например

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

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

}

Я пытаюсь протестировать такой класс, как

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

Следуя этому ответу, я попытался просто протестировать макет с помощью следующего кода, но, похоже, у меня возникли проблемы с перечисление, вызывающее его конструктор

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);
    }
}

Использование интерфейса кажется несколько многообещающим, но я сомневаюсь, что это лучший способ решить эту проблему.

Похоже, PowerMockito тоже многообещающий , но я хотел бы сохранить это в крайнем случае по разным причинам.

Итак, как я могу имитировать этот синглтон перечисления, не вызывая его конструктор?


person Azianese    schedule 25.06.2020    source источник
comment
Зачем - черт возьми - нужно издеваться над enum?   -  person Seelenvirtuose    schedule 25.06.2020
comment
@Seelenvirtuose Я хотел бы убедиться, что doSomething () вызывает SingletonObject.INSTANCE.callDB (); без фактического вызова БД   -  person Azianese    schedule 25.06.2020


Ответы (1)


Попробуйте что-нибудь подобное. Это создает частичную имитацию MyClass и Mock SingletonObject, вызывает (настоящий) метод doSomething класса MyClass и подтверждает, что метод (mock) callDB () объекта SingletonObject вызывается им ровно один раз.

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

    new Expectations(clz)
    {
        {
            SingletonObject.INSTANCE.callDB();
            times = 1;
        }
    };
    clz.doSomething();
}
person Jeff Bennett    schedule 01.07.2020
comment
При попытке этого я получаю следующую ошибку: java.lang.InternalError: ошибка переопределения класса: недопустимый класс в sun.instrument.InstrumentationImpl.retransformClasses0 (собственный метод) - person Azianese; 08.07.2020