我使用模拟和 MockDispatcherFactory 进行单元测试来测试我的 Rest 应用程序。这些适用于以前版本的 Resteasy,但当更新到 3.15.0.Final (Wildfly 24) 时,不再注入 @Context 对象。这是我的测试代码:
private MockHttpResponse request(final Method method, final String uri, final HttpServletRequest mockedRequest,
final Object service, final Optional<byte[]> content,
final Optional<String> contentType,
final Optional<Map<Class<?>, Object>> contextObjects,
final Optional<Map<String, String>> cookies)
throws URISyntaxException, IOException, ClassNotFoundException, InvocationTargetException,
NoSuchMethodException, InstantiationException, IllegalAccessException {
final Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
dispatcher.getRegistry().addSingletonResource(service);
dispatcher.getDefaultContextObjects().put(HttpServletRequest.class, mockedRequest);
dispatcher.getProviderFactory().registerProviderInstance(new JacksonTestConfigurator());
if (contextObjects.isPresent()) {
for (Map.Entry<Class<?>, Object> contextObject : contextObjects.get().entrySet()) {
dispatcher.getDefaultContextObjects().put(contextObject.getKey(), contextObject.getValue());
pushContext(contextObject.getKey(), contextObject.getValue());
}
}
addMappings(dispatcher);
final MockHttpRequest request = performRequest(method, uri);
request.accept(MediaType.APPLICATION_JSON);
request.contentType(contentType.isPresent() ? contentType.get() : MediaType.APPLICATION_JSON_TYPE.toString());
if (cookies.isPresent()) {
for (Map.Entry<String, String> cookieEntry : cookies.get().entrySet()) {
request.cookie(cookieEntry.getKey(), cookieEntry.getValue());
}
}
if (content.isPresent()) {
request.content(content.get());
}
final MockHttpResponse response = new MockHttpResponse();
dispatcher.invoke(request, response);
return response;
}
@SuppressWarnings("unchecked")
public <T> void pushContext(Class<?> clasz, Object obj) {
Class<T> type = (Class<T>) clasz;
ResteasyProviderFactory.pushContext(type, (T) obj);
}
我尝试了两种方法,正如你在代码中看到的:
public void updatePassword(@PathParam(value = "panelist") String panelistId,
@Context Optional<AuthenticatedUser> authenticatedPanelist,
CurrentAndNewCredentialsDto dto)
throws ForbiddenException, InvalidArgumentException, UnexpectedException {
assertAuthenticatedUserHasAccessToPanelistResource(authenticatedUser, panelistId);
CurrentAndNewPassword currentAndNewPassword =
CurrentAndNewCredentialsDtoMapper.INSTANCE.toPasswordModel(dto);
Try<Void> result = facade.updatePassword(panelistId, currentAndNewPassword);
if (result.isFailure()) {
Throwable failure = result.getFailure();
if (failure instanceof InvalidArgumentException) {
logger.warn("Failure when panelist tries to updatePassword, for panelist {}", panelistId, failure);
throw (InvalidArgumentException) failure;
} else {
throw new UnexpectedException(failure);
}
}
}
有什么建议吗?
我尝试了两种方法,正如你在代码中看到的:
我希望 @Context 注入可以像旧版本一样工作
我找到问题所在了。 我向上下文推送了一个可选的,而不是直接推送所需的对象,因为在休息端点我想要一个可选的。事实证明,如果您推送对象并期望可选的 Resteasy 为您包装它,那么而不是:
ResteasyProviderFactory.pushContext(Optional.class, Optional.ofNullable(authenticatedUser));
必须是:
ResteasyProviderFactory.pushContext(AuthenticatedUser.class, authenticatedUser);
然后在端点中,您可以作为可选注入:
@Context Optional<AuthenticatedUser> authenticatedUser