【问题标题】:junit5 + weld + mockito extension, how to inject @Context objectjunit5 +weld + mockito 扩展,如何注入@Context 对象
【发布时间】:2020-02-13 11:03:59
【问题描述】:

这是我的 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 始终为空,可能是因为没有注入但它是一个上下文对象。

所以真正的问题是,如何生成 HttpServletRequest 模拟并作为 @Context 对象注入?

【问题讨论】:

    标签: mockito junit5-extension-model weld-junit5


    【解决方案1】:

    用户mkouba也向weld-junit组寻求帮助后给出了最终解决方案。

    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

    【讨论】:

      【解决方案2】:

      我们在尝试@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();
       }
      

      您可以通过 @Mocking HttpServletRequestContext 来做同样的事情,然后在注入图中设置它们。

      【讨论】:

      • 对不起,我试过了,但有一些东西丢失了,它说在你的测试用例上找不到用@InjectMocks 注释的实例化字段。我尝试在 HttpServletRequest servletRequest 上申请,但它不起作用,因为它是一个接口
      • ConfigApiResource 必须注解 @InjectMocks,并且它使用的每个 bean 都是模拟的。根据您的意图(您是在进行集成测试还是真正的单元测试?)这可能是可取的。我也有第二个想法...您可以为请求对象创建一个 @Producer bean 并将其包含在您的 Weld 配置中吗?
      猜你喜欢
      • 1970-01-01
      • 2016-12-27
      • 1970-01-01
      • 2012-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-11
      • 2014-01-27
      相关资源
      最近更新 更多