AEM 6.3,wcm.io:@Activate 方法中的 sling MockResource null
AEM 6.3, wcm.io: sling MockResource null in @Activate method
我有一个具有@Activate 方法的OSGI 服务。在 activate 方法中,我调用了一个名为 '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);
您必须调用 buildTitleList
或 Activate
(新的 Java 编码约定?)因为 "OSGI declarative service annotations" 在单元测试中没有用。您只是没有容器来调用这些方法。
感谢@Jens,我发现 ResourceResolver 现在实现了 AutoClosable 接口(从 6.2 开始,我们使用的是 6.3.1.2)所以我可以删除我们的自定义工厂并使用默认的 ResourceResolverFactory,现在一切正常。
我有一个具有@Activate 方法的OSGI 服务。在 activate 方法中,我调用了一个名为 '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);
您必须调用 buildTitleList
或 Activate
(新的 Java 编码约定?)因为 "OSGI declarative service annotations" 在单元测试中没有用。您只是没有容器来调用这些方法。
感谢@Jens,我发现 ResourceResolver 现在实现了 AutoClosable 接口(从 6.2 开始,我们使用的是 6.3.1.2)所以我可以删除我们的自定义工厂并使用默认的 ResourceResolverFactory,现在一切正常。