Как создать конструктор по умолчанию с Byte Buddy

Я хочу перехватить вызовы некоторых методов в одном из моих классов, но у этих классов нет конструктора по умолчанию.

Учитывая следующий класс, как мне настроить Byte Buddy, чтобы он также создавал открытый конструктор без аргументов, чтобы иметь возможность создавать сгенерированный класс?

public class GetLoggedInUsersSaga extends AbstractSpaceSingleEventSaga {
    private final UserSessionRepository userSessionRepository;

    @Inject
    public GetLoggedInUsersSaga(final UserSessionRepository userSessionRepository) {
        this.userSessionRepository = userSessionRepository;
    }

    @StartsSaga
    public void handle(final GetLoggedInUsersRequest request) {
       // this is the method in want to intercept
    }
}

РЕДАКТИРОВАТЬ: Конкретный вариант использования этого для упрощения настройки модульного теста.
В настоящее время мы всегда должны писать что-то вроде этого:

@Test
public void someTest() {
   // Given

   // When
   GetLoggedInUsersRequest request = new GetLoggedInUsersRequest();
   setMessageForContext(request); // <-- always do this before calling handle
   sut.handle(request);

   // Then
}

Я подумал, что было бы неплохо создать прокси в методе @Before, который автоматически устанавливает контекст для вас.

@Before
public void before()  {
    sut = new GetLoggedInUsersSaga(someDependency);
    sut = intercept(sut);
}

@Test
public void someTest() {
   // Given

   // When
   GetLoggedInUsersRequest request = new GetLoggedInUsersRequest();
   sut.handle(request);

   // Then
}

Я немного поиграл, но, к сожалению, у меня не получилось.

public <SAGA extends Saga> SAGA intercept(final SAGA sagaUnderTest) throws NoSuchMethodException, IllegalAccessException, InstantiationException {
    return (SAGA) new ByteBuddy()
            .subclass(sagaUnderTest.getClass())
            .defineConstructor(Collections.<Class<?>>emptyList(), Visibility.PUBLIC)
            .intercept(MethodCall.invokeSuper())
            .method(ElementMatchers.isAnnotatedWith(StartsSaga.class))
            .intercept(
                    MethodDelegation.to(
                            new Object() {
                                @RuntimeType
                                public Object intercept(
                                        @SuperCall Callable<?> c,
                                        @Origin Method m,
                                        @AllArguments Object[] a) throws Exception {
                                    setMessageForContext((Message) a[0]);
                                    return c.call();
                                }
                            }))
            .make()
            .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
            .getLoaded()
            .newInstance();
}

К сожалению, теперь я получаю (вероятно, потому что вызов Ctor все еще не правильно настроен)

java.lang.IllegalStateException: Cannot invoke public com.frequentis.ps.account.service.audit.GetLoggedInUsersSaga$ByteBuddy$zSZuwhtR() as a super method

Это даже правильный подход?
Должен ли я здесь использовать байтовый компаньон или есть более простой / другой способ?

Ответы на вопрос(1)

Ваш ответ на вопрос