Как создать конструктор по умолчанию с 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
Это даже правильный подход?
Должен ли я здесь использовать байтовый компаньон или есть более простой / другой способ?