junit5 + weld + mockito 扩展,如何注入@Context 对象
junit5 + weld + mockito extension, how to inject @Context object
这是我的 REST 资源:
@Context
HttpServletRequest webRequest;
@Override
public DomainConfig get() {
return configDelegate.get(webRequest.getHeader("Origin"));
}
我已经使用 Junit 5 + Weld / Mockito 扩展构建了我的单元测试。
@MockitoSettings(strictness = Strictness.STRICT_STUBS)
@ExtendWith(MockitoExtension.class)
@DisplayName("configs resource")
@EnableWeld
public class ConfigApiResourceTest {
@Mock
HttpServletRequest servletRequest;
@WeldSetup
public WeldInitiator weld = WeldInitiator
.from(
MockCommonResources.class,
ConfigApiResource.class,
ConfigDelegate.class,
ConfigService.class,
etc etc
)
.addBeans(createHttpServletRequest())
.activate(
RequestScoped.class,
ApplicationScoped.class
)
.build();
Bean<?> createHttpServletRequest() {
return MockBean.builder()
.types(HttpServletRequest.class)
.create(o -> servletRequest)
.build();
}
@Test
@DisplayName("config")
void config(ConfigApiResource configApiResource) {
final String url = "areaclient.infocert.it";
when(servletRequest.getHeader("Origin")).thenReturn(url);
final DomainConfig output = configApiResource.get();
assertNotNull(output);
}
}
问题是 HttpServletRequest webRequest 始终为 null,可能是因为未注入但它是上下文对象。
所以真正的问题是,如何生成 HttpServletRequest 模拟并作为 @Context 对象注入?
我们在尝试 @Inject private Boolean securityEnabled;
对象时遇到了这个问题,因为无法模拟布尔值。我们用自定义 JUnit/Mockito 扩展解决了它:https://github.com/exabrial/mockito-object-injection
@InjectionMap
private Map<String, Object> injectionMap = new HashMap<>();
@BeforeEach
public void beforeEach() throws Exception {
injectionMap.put("securityEnabled", Boolean.TRUE);
}
@AfterEach
public void afterEach() throws Exception {
injectionMap.clear();
}
您可以通过 @Mock
ing HttpServletRequest
和 Context
然后在注入映射中设置它们来做同样的事情。
在向 weld-junit 组寻求帮助后,用户 mkouba 给出了最终解决方案。
final Weld weldBase = WeldInitiator.createWeld()
.addBeanClasses(
MockCommonResources.class,
ConfigApiResource.class,
ConfigDelegate.class,
ConfigService.class,
etc etc
)
.addContainerLifecycleObserver(ContainerLifecycleObserver.processAnnotatedType()
.notify(pat -> pat.configureAnnotatedType()
.filterFields(m -> m.isAnnotationPresent(Context.class))
.forEach(m -> m.add(javax.enterprise.inject.literal.InjectLiteral.INSTANCE))));
@WeldSetup
public WeldInitiator weld = WeldInitiator
.from(
weldBase
)
.activate(
RequestScoped.class,
ApplicationScoped.class
)
.addBeans(createHttpServletRequest())
.build();
通过在 Context 注释上添加观察者,servletRequest 模拟被正确地注入到 ConfigApiResource
这是我的 REST 资源:
@Context
HttpServletRequest webRequest;
@Override
public DomainConfig get() {
return configDelegate.get(webRequest.getHeader("Origin"));
}
我已经使用 Junit 5 + Weld / Mockito 扩展构建了我的单元测试。
@MockitoSettings(strictness = Strictness.STRICT_STUBS)
@ExtendWith(MockitoExtension.class)
@DisplayName("configs resource")
@EnableWeld
public class ConfigApiResourceTest {
@Mock
HttpServletRequest servletRequest;
@WeldSetup
public WeldInitiator weld = WeldInitiator
.from(
MockCommonResources.class,
ConfigApiResource.class,
ConfigDelegate.class,
ConfigService.class,
etc etc
)
.addBeans(createHttpServletRequest())
.activate(
RequestScoped.class,
ApplicationScoped.class
)
.build();
Bean<?> createHttpServletRequest() {
return MockBean.builder()
.types(HttpServletRequest.class)
.create(o -> servletRequest)
.build();
}
@Test
@DisplayName("config")
void config(ConfigApiResource configApiResource) {
final String url = "areaclient.infocert.it";
when(servletRequest.getHeader("Origin")).thenReturn(url);
final DomainConfig output = configApiResource.get();
assertNotNull(output);
}
}
问题是 HttpServletRequest webRequest 始终为 null,可能是因为未注入但它是上下文对象。
所以真正的问题是,如何生成 HttpServletRequest 模拟并作为 @Context 对象注入?
我们在尝试 @Inject private Boolean securityEnabled;
对象时遇到了这个问题,因为无法模拟布尔值。我们用自定义 JUnit/Mockito 扩展解决了它:https://github.com/exabrial/mockito-object-injection
@InjectionMap
private Map<String, Object> injectionMap = new HashMap<>();
@BeforeEach
public void beforeEach() throws Exception {
injectionMap.put("securityEnabled", Boolean.TRUE);
}
@AfterEach
public void afterEach() throws Exception {
injectionMap.clear();
}
您可以通过 @Mock
ing HttpServletRequest
和 Context
然后在注入映射中设置它们来做同样的事情。
在向 weld-junit 组寻求帮助后,用户 mkouba 给出了最终解决方案。
final Weld weldBase = WeldInitiator.createWeld()
.addBeanClasses(
MockCommonResources.class,
ConfigApiResource.class,
ConfigDelegate.class,
ConfigService.class,
etc etc
)
.addContainerLifecycleObserver(ContainerLifecycleObserver.processAnnotatedType()
.notify(pat -> pat.configureAnnotatedType()
.filterFields(m -> m.isAnnotationPresent(Context.class))
.forEach(m -> m.add(javax.enterprise.inject.literal.InjectLiteral.INSTANCE))));
@WeldSetup
public WeldInitiator weld = WeldInitiator
.from(
weldBase
)
.activate(
RequestScoped.class,
ApplicationScoped.class
)
.addBeans(createHttpServletRequest())
.build();
通过在 Context 注释上添加观察者,servletRequest 模拟被正确地注入到 ConfigApiResource