【问题标题】:How can I inject an @Context-annotated field into a RestEasy @Provider?如何将 @Context 注释字段注入 RestEasy @Provider?
【发布时间】:2019-08-31 20:21:09
【问题描述】:

在 JBoss 容器中使用 RestEasy,我有一个带有 @Provider 注释的 ExceptionMapper,它可以通过 @Context 注释访问 HttpServletRequestHttpServletResponse,如下所示:

@Provider
public class MyExceptionMapper implements ExceptionMapper<Throwable> {
  @Context
  private HttpServletRequest httpServletRequest;

  @Context
  private HttpServletResponse httpServletResponse;

  @Override
  public Response toResponse(final Throwable exception) {
    ...
    return response;
  }
}

我是 RestEasy 的新手,来自 Spring 背景,所以天真地以为我能够注入这两个字段并在单元测试中模拟它们,但这似乎比我预期的要难!

如果模拟框架是相关的,我正在使用 JMockit,而且我也是新手。到目前为止,我已经能够成功地将我对 Mockito 的知识应用到它上面。

除了在我的单元测试中运行嵌入式容器的许多建议外,我没有通过搜索该主题找到太多东西。我并不完全反对,但是当我只是想写一个简单的单元测试时,感觉有点矫枉过正。

我在测试中尝试了几件事,最近是这样的:

public class MyExceptionMapperTest {
  @Injectable
  private HttpServletRequest httpServletRequest;

  @Injectable
  private HttpServletResponse httpServletResponse;

  @Tested
  private MyExceptionMapper exceptionMapper;

  @Test
  public void test() {
    exceptionMapper.toResponse(new Throwable());
  }
}

但这会在我第一次引用@Context 字段之一时导致MyExceptionMapper 中的NullPointerException,这告诉我它们没有被注入。

我也试过了:

  • 使用@Mocked 代替@Injectable
  • 直接实例化MyExceptionMapper 有和没有@Tested 注释;
  • 在我的测试中创建Expectations;和
  • 上述的每一个排列

在所有情况下,@Context-annotated 字段都是null

希望我只是遗漏了一些非常明显的东西吗?

【问题讨论】:

  • 你使用-javaagent参数初始化JMockit了吗?
  • @Rogério - 不知情。我只是在 IntelliJ 中将测试作为普通 JUnit 测试运行,并且在 Maven POM 中看不到对 -javaagent 的任何引用。我应该使用它吗?
  • 如果您使用的是最新版本的 JMockit,那么可以。

标签: java jboss resteasy jmockit


【解决方案1】:

在没有更好的答案的情况下,我最终在测试中使用反射来为这两个属性注入值。不理想,但它有效:

public class MyExceptionMapperTest {
  @Mocked
  private HttpServletRequest mockHttpServletRequest;

  @Mocked
  private HttpServletResponse mockHttpServletResponse;

  private MyExceptionMapper exceptionMapper = new MyExceptionMapper();

  @Before
  public void setup() {
    Field httpServletRequest = exceptionMapper.getClass().getDeclaredField("httpServletRequest");
    httpServletRequest.setAccessible(true);
    httpServletRequest.set(exceptionMapper, mockHttpServletRequest);

    Field httpServletResponse = exceptionMapper.getClass().getDeclaredField("httpServletResponse");
    httpServletResponse.setAccessible(true);
    httpServletResponse.set(exceptionMapper, mockHttpServletResponse);
  }
}

然后在我的测试中,我可以正常设置两个 @Mocked 值的期望和验证。

我不是反思方面的专家,所以这可能不是最好/最有效的方法,但它足以满足我的需求。

【讨论】:

    猜你喜欢
    • 2020-03-08
    • 1970-01-01
    • 2014-12-04
    • 2012-10-01
    • 2019-04-30
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 2012-02-19
    相关资源
    最近更新 更多