【问题标题】:AEM 6.3, wcm.io: sling MockResource null in @Activate methodAEM 6.3,wcm.io:@Activate 方法中的 Sling MockResource null
【发布时间】:2018-08-03 13:24:26
【问题描述】:

我有一个具有 @Activate 方法的 OSGI 服务。在激活方法中,我调用了一个名为“buildTitleList”的方法,在该方法中我查询一些资源(页面)并将它们的标题收集在一个列表中。此代码在运行环境中运行,但不在我的单元测试中。

我通过以下方式在我的上下文中创建页面:

aemContext.create().page("/content/test-page', "/apps/platform-company/templates/home-page", "test-tile");

如果我调试我的单元测试,我可以看到我在“buildTitleList”中查询的资源是空的(注意:我确定我的路径是正确的)

当我在单元测试中直接调用“buildTitleList”时,它确实有效。这是正常行为吗,有没有办法确保 @Activate 方法也可以在上下文中看到新创建的页面?

测试:

@Test
public void checkTitles() {
    TitleService titleService = context.getService(TitleService.class);
    System.out.println(); //If I set a breakpoint here and look into the TitleService instance the list of titles is still 0
}

标题服务:

public class TitleService {

    private List<String> titles;

    public TitleService() {
        this.titles = new CopyOnWriteArrayList<>();
    }

    ...
    public void buildTitleList() throws RepositoryException, LoginException, WCMException {

        // Gather title code here (incl. newlist). This works on a running instance but the resoure is always null when calle from within an @Activa method

        this.titles.addAll(newlist);

    }
    ...

    @Activate
    protected void Activate() {
        buildTitleList();       
    }
}

设置代码:

...

public static AemContext getAemContext(RunMode runMode) {
    if (aemContext != null) {
        aemContext.runMode(runMode.getValue());
        return aemContext;
    } else {
        aemContext = newAemContext();
        aemContext.runMode(runMode.getValue());
        return aemContext;
    }
}

public static AemContext newAemContext() {
    return new AemContextBuilder()
            .resourceResolverType(ResourceResolverType.JCR_MOCK)
            .afterSetUp(SETUP_CALLBACK)
            .build();
}

private static final AemContextCallback SETUP_CALLBACK = aemContext -> {

    // context path strategy
    MockCAConfig.contextPathStrategyRootTemplate(aemContext, Template.HOME_PAGE.getValue());

    // register sling models
    ...

    aemContext.registerInjectActivateService(new AutoClosableResourceResolverFactory());
    aemContext.registerInjectActivateService(new TitleService());

    createBlueprintPages(aemContext);

    TestInformation testInformation = TestInformation.getInstance();

    for (TestLiveCopyInformation info : testInformation.getLiveCopyInformationList()) {
        aemContext.load().json(info.getResourcePath(), info.getContentRoot() + "/" + info.getLanguage().getIsoCode());
    }

    // set default current page
    aemContext.currentPage(CONTENT_ROOT);

};

...

测试规则:

@Rule
public final AemContext context = AppAemContext.getAemContext(RunMode.AUTHOR);

【问题讨论】:

  • 你能发布更多你的测试代码吗?至少你的设置方法和测试方法。
  • 您是否注册并激活了您的TitleService(参见context.registerInjectActivateService)?例如在@Before 方法中?
  • 您能添加更多代码吗?您的 @Before 方法或您在测试等中使用的任何其他设置方法。
  • 请不要注册自己的(Autoclosable)ResourceResolverFactory。 AEM 上下文已经有它自己的 RRF,例如,如果您调用 aemContext.create().page(),它会使用它。但是您自己的服务可能会绑定到您另外注册的其他 RRF。您基本上必须 RRF,它可能在模拟 JCR 上有自己的“视图”,这意味着向其中一个节点添加节点不会使其对另一个节点可用。
  • 您引用AutoClosableResourceResolverFactory 是否有原因(这是您自己的实现,不是吗)?为什么您的服务没有使用正常的ResourceResolverFactory?如果您仍需要使用 ACRRF,您可能需要创建一个使用 aem 上下文资源解析器的模拟 ACRRF。否则你将无法使用 wcm.io 提供的大部分资源相关 API。

标签: mocking osgi adobe aem sling


【解决方案1】:

您必须调用buildTitleListActivate(新的Java 编码约定?),因为“OSGI 声明性服务注释”在单元测试中没有用处。你根本没有容器来调用这些方法。

【讨论】:

  • WCM IO 提供对 OSGI R6 及其激活方法的支持。我还可以看到在调试模式下调用了 activate 方法。
【解决方案2】:

感谢@Jens,我发现 ResourceResolver 现在实现了 AutoClosable 接口(从 6.2 开始,我们使用的是 6.3.1.2),因此我可以删除我们的自定义工厂并使用默认的 ResourceResolverFactory,现在一切正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-13
    • 2020-03-30
    相关资源
    最近更新 更多