使用具有真正 Jackrabbit 实施的 wcm.io AEM Mocks 从 JSON 导入内容
Importing content from JSON using wcm.io AEM Mocks with a real Jackrabbit implementation
我正在尝试使用 wcm.io Testing AEM Mocks
编写集成测试
我要测试的代码在存储库中保存了一些数据,因此我想验证在我 运行 测试方法后是否实际存储了正确的内容。
在我之前的测试中,我使用了JCR_MOCK
Resource Resolver Type,像这样:
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Rule
public final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK);
private MyClass tested;
@Before
public void setUp() throws Exception {
//here, I load an entire page,
//from which my tested class reads some data
aemContext.load().json("/jcrdata/myPage.json", "/etc/mystuff/myTool");
tested = new MyClass(aemContext.resourceResolver());
}
@Test
public void interactWithTheRepository() {
SomeResult result = tested.interactWithTheRepository();
//assertions here
}
}
只要我只想从模拟存储库读取数据或假装我保存一些东西,这就很好用。当我真正想验证某些数据是否已被测试 class.
保存在存储库中时,问题就开始了
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Rule
public final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK);
private MyClass tested;
@Before
public void setUp() throws Exception {
//here, I load an entire page,
//on which the instance of my tested class later saves some data
aemContext.load().json("/jcrdata/myPage.json", "/etc/mystuff/myTool");
tested = new MyClass(aemContext.resourceResolver());
}
@Test
public void storeDataInTheRepository() {
tested.storeDataInTheRepository();
//this comes up as null because the JCR_Mock resolver
//does not use an actual repository and nothing is stored
Resource result = aemContext.resourceResolver().getResource("/etc/mystuff/myTool/somethingSavedByMyClassInstance");
//assertions here
}
}
我相信这可以通过使用实际存储库的 JCR_JACKRABBIT
Resource Resolver Type 来实现。但是,我很难将数据加载到模拟存储库中。一旦我使用 JCR_JACKRABBIT
代替 JCR_MOCK
,我的 setUp
方法就会失败并显示 NullPointerException
(为清楚起见,省略了 class 的其他部分)
@Rule
public final AemContext aemContext = new AemContext(ResourceResolverType.JCR_JACKRABBIT);
@Before
public void setUp() throws Exception {
//This line fails with an NPE
aemContext.load().json("/jcrdata/myPage.json", "/etc/mystuff/myTool");
tested = new MyClass(aemContext.resourceResolver());
}
我调试了代码并注意到它在尝试创建资源层次结构时失败了。
java.lang.NullPointerException
at org.apache.sling.resourceresolver.impl.ResourceResolverImpl.create(ResourceResolverImpl.java:1044)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.createResourceHierarchy(ContentLoader.java:183)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.createResourceHierarchy(ContentLoader.java:178)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.json(ContentLoader.java:155)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.json(ContentLoader.java:120)
at com.foo.bar.baz.MyClassTest.setUp(MyClassTest.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.rules.ExternalResource.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access[=15=]0(ParentRunner.java:53)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
根据文档,Sling 测试应在尝试从 JSON 文档加载页面时处理所有父资源的创建:
Resource org.apache.sling.testing.mock.sling.loader.ContentLoader.json(String classpathResource, String destPath)
Import content of JSON file into repository. Auto-creates parent hierarchies as nt:unstrucured nodes if missing.
但是,当到达存储库的根并且应该在 /
下创建一个 etc
节点时,ContentLoader
的方法 createResourceHierarchy
调用ResourceResolver
具有以下参数:
resourceResolver.create(null, ResourceUtil.getName("/etc"), props);
其中 props
是以下结构的简单 HashMap
:{jcr:primaryType=nt:unstructured}
,导致 NullPointerException
(由于 null
父资源被传递)
我不确定这是错误还是我做错了什么,the Sling Testing documentation 提到了 JCR_JACKRABBIT
资源解析器类型:
To import Sling content you have to fully register all node types required for the data
但我不确定如何解释。
我正在使用:
io.wcm.testing.aem-mock 1.2.2
org.apache.sling.testing.sling-mock-jackrabbit 0.1.0
如何在使用 JCR_JACKRABBIT
资源解析器实现时从 JSON 文件加载内容?
它告诉您您的实现不知道结构中的不同节点类型及其约束,无法创建这样的节点。
您是否尝试过将节点类型定义 (nodetype.cnd) 放入您的类路径中(只需将其放入 src/test/resources 目录中)并使用 RepositoryUtil 加载它?
RepositoryUtil.registerNodeType(session, getClass().getResourceAsStream("nodetypes.cnd"));
感谢 I was able to take a couple steps forward but kept facing different errors. In the meantime, I opened a topic on the wcm.io Developers mailing group 了解是否可以通过更平易近人的方式实现我的目标。答案分为两部分。第一个描述了为我试图涵盖的特定用例编写测试可以做什么。后者描述了我在实际使用 JCR_JACKRABBIT
资源解析器类型时的发现。
测试 类 写入存储库
原来我从 JCR_MOCK
切换到 JCR_JACKRABBIT
资源解析器类型的速度太快了。 JCR_MOCK
足以满足我的情况,如下所示:
- 从 class 路径
上的 JSON 文件加载内容
- 针对模拟存储库执行测试 class 的方法(class 应该从存储库中读取一些内容并将更多内容存储到其中)
- 读取被测者写的内容class并断言是否符合预期值
数据实际写入内存存储库。我无法阅读它是我自己的错误导致的,而不是使用的实现。
正在将 JSON 加载到 JCR_JACKRABBIT-backed AemContext
我设法按照 的建议走得很远,但我还没有成功地让这个实施工作完全顺利。这是我所做的:
我在 setUp 方法中添加了以下几行:
Session session = aemContext.resourceResolver().adaptTo(Session.class);
RepositoryUtil.registerNodeType(session, getClass().getResourceAsStream("/nodetypes/types.cnd"));
就在aemContext.load().json("/jcrdata/myPage.json", "/etc/mystuff/myTool");
之前
types.cnd
是我的 class 路径上的一个文件,其中包含在我的 AEM 实例上的 CRX 存储库中找到的节点类型定义。
这让我摆脱了 NPE,但由于某些原因,cq:Page
和 cq:PageContent
节点类型无法识别。这会导致 PersistenceException
在调用 aemContext.load().json("/jcrdata/myPage.json", "/etc/mystuff/myTool");
时抛出,如果这些类型中的任何一个节点存在于加载的 JSON 中。
问题似乎是 cq:Page
和 cq:PageContent
节点类型仍然找不到,尽管我已明确将它们添加到我的 types.cnd
文件中。我从 docs.adobe.com 中获取了这两种类型的定义,并确保包含这些定义中使用的名称空间前缀。
这是我的内容 cq:Page 中出现的堆栈跟踪示例 JSON:
java.lang.RuntimeException: org.apache.sling.api.resource.PersistenceException: Unable to create node at /etc/foo/bar/baz
at org.apache.sling.testing.mock.sling.loader.ContentLoader.json(ContentLoader.java:167)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.json(ContentLoader.java:120)
at com.foo.bar.baz.MyClassTest.setUp(MyClassTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.rules.ExternalResource.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access[=11=]0(ParentRunner.java:53)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.apache.sling.api.resource.PersistenceException: Unable to create node at /etc/foo/bar/baz
at org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProvider.create(JcrResourceProvider.java:473)
at org.apache.sling.resourceresolver.impl.tree.ResourceProviderEntry.create(ResourceProviderEntry.java:479)
at org.apache.sling.resourceresolver.impl.ResourceResolverImpl.create(ResourceResolverImpl.java:1053)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.createResource(ContentLoader.java:217)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.json(ContentLoader.java:163)
... 30 more
Caused by: javax.jcr.nodetype.NoSuchNodeTypeException: {http://www.day.com/jcr/cq/1.0}Page
at org.apache.jackrabbit.core.nodetype.NodeTypeRegistry.getEffectiveNodeType(NodeTypeRegistry.java:1024)
at org.apache.jackrabbit.core.nodetype.NodeTypeRegistry.getEffectiveNodeType(NodeTypeRegistry.java:487)
at org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl.getNodeType(NodeTypeManagerImpl.java:177)
at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1240)
at org.apache.jackrabbit.core.session.AddNodeOperation.perform(AddNodeOperation.java:111)
at org.apache.jackrabbit.core.session.AddNodeOperation.perform(AddNodeOperation.java:37)
at org.apache.jackrabbit.core.session.SessionState.perform(SessionState.java:200)
at org.apache.jackrabbit.core.ItemImpl.perform(ItemImpl.java:91)
at org.apache.jackrabbit.core.NodeImpl.addNodeWithUuid(NodeImpl.java:1769)
at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1729)
at org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProvider.create(JcrResourceProvider.java:435)
... 34 more
但是,只要将所有 cq:Page
和 cq:PageContent
类型替换为 nt:unstructured
,我就可以成功导入内容
这允许我针对存储库执行我的代码并读取我测试的 class 写在那里的内容,但我有点担心我的测试内容具有与其真实对应的节点类型不同的事实可能会影响测试结果在某些情况下。
JCR_JACKRABBIT
还需要创建一个 Derby 数据库,它不会在测试执行之间被清除。
总而言之,JCR_JACKRABBIT
引入了一些问题,并且在我的具体情况下与 JCR_MOCK
相比没有任何优势。建议我不要使用它,除非我真的需要模拟 JCR_MOCK
不支持的高级功能,例如事件或版本控制。
引用Stefan Seifert's comment on the wcm.io Developers mailing group
use JCR_JACKRABBIT only if you need special features not supported by JCR_MOCK, e.g. eventing, versioning etc. but only then, it’s the most heavyweight and most inperformant choice and not used much currently. we did some small improvements on this integration in the current trunk of sling-mock-jackrabbit in sling, esp. concering the content loader and special properties that cannot be imported, but this is not released yet.
我正在尝试使用 wcm.io Testing AEM Mocks
编写集成测试我要测试的代码在存储库中保存了一些数据,因此我想验证在我 运行 测试方法后是否实际存储了正确的内容。
在我之前的测试中,我使用了JCR_MOCK
Resource Resolver Type,像这样:
@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Rule
public final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK);
private MyClass tested;
@Before
public void setUp() throws Exception {
//here, I load an entire page,
//from which my tested class reads some data
aemContext.load().json("/jcrdata/myPage.json", "/etc/mystuff/myTool");
tested = new MyClass(aemContext.resourceResolver());
}
@Test
public void interactWithTheRepository() {
SomeResult result = tested.interactWithTheRepository();
//assertions here
}
}
只要我只想从模拟存储库读取数据或假装我保存一些东西,这就很好用。当我真正想验证某些数据是否已被测试 class.
保存在存储库中时,问题就开始了@RunWith(MockitoJUnitRunner.class)
public class MyClassTest {
@Rule
public final AemContext aemContext = new AemContext(ResourceResolverType.JCR_MOCK);
private MyClass tested;
@Before
public void setUp() throws Exception {
//here, I load an entire page,
//on which the instance of my tested class later saves some data
aemContext.load().json("/jcrdata/myPage.json", "/etc/mystuff/myTool");
tested = new MyClass(aemContext.resourceResolver());
}
@Test
public void storeDataInTheRepository() {
tested.storeDataInTheRepository();
//this comes up as null because the JCR_Mock resolver
//does not use an actual repository and nothing is stored
Resource result = aemContext.resourceResolver().getResource("/etc/mystuff/myTool/somethingSavedByMyClassInstance");
//assertions here
}
}
我相信这可以通过使用实际存储库的 JCR_JACKRABBIT
Resource Resolver Type 来实现。但是,我很难将数据加载到模拟存储库中。一旦我使用 JCR_JACKRABBIT
代替 JCR_MOCK
,我的 setUp
方法就会失败并显示 NullPointerException
(为清楚起见,省略了 class 的其他部分)
@Rule
public final AemContext aemContext = new AemContext(ResourceResolverType.JCR_JACKRABBIT);
@Before
public void setUp() throws Exception {
//This line fails with an NPE
aemContext.load().json("/jcrdata/myPage.json", "/etc/mystuff/myTool");
tested = new MyClass(aemContext.resourceResolver());
}
我调试了代码并注意到它在尝试创建资源层次结构时失败了。
java.lang.NullPointerException
at org.apache.sling.resourceresolver.impl.ResourceResolverImpl.create(ResourceResolverImpl.java:1044)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.createResourceHierarchy(ContentLoader.java:183)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.createResourceHierarchy(ContentLoader.java:178)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.json(ContentLoader.java:155)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.json(ContentLoader.java:120)
at com.foo.bar.baz.MyClassTest.setUp(MyClassTest.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.rules.ExternalResource.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access[=15=]0(ParentRunner.java:53)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
根据文档,Sling 测试应在尝试从 JSON 文档加载页面时处理所有父资源的创建:
Resource org.apache.sling.testing.mock.sling.loader.ContentLoader.json(String classpathResource, String destPath)
Import content of JSON file into repository. Auto-creates parent hierarchies as nt:unstrucured nodes if missing.
但是,当到达存储库的根并且应该在 /
下创建一个 etc
节点时,ContentLoader
的方法 createResourceHierarchy
调用ResourceResolver
具有以下参数:
resourceResolver.create(null, ResourceUtil.getName("/etc"), props);
其中 props
是以下结构的简单 HashMap
:{jcr:primaryType=nt:unstructured}
,导致 NullPointerException
(由于 null
父资源被传递)
我不确定这是错误还是我做错了什么,the Sling Testing documentation 提到了 JCR_JACKRABBIT
资源解析器类型:
To import Sling content you have to fully register all node types required for the data
但我不确定如何解释。
我正在使用:
io.wcm.testing.aem-mock 1.2.2
org.apache.sling.testing.sling-mock-jackrabbit 0.1.0
如何在使用 JCR_JACKRABBIT
资源解析器实现时从 JSON 文件加载内容?
它告诉您您的实现不知道结构中的不同节点类型及其约束,无法创建这样的节点。
您是否尝试过将节点类型定义 (nodetype.cnd) 放入您的类路径中(只需将其放入 src/test/resources 目录中)并使用 RepositoryUtil 加载它?
RepositoryUtil.registerNodeType(session, getClass().getResourceAsStream("nodetypes.cnd"));
感谢 JCR_JACKRABBIT
资源解析器类型时的发现。
测试 类 写入存储库
原来我从 JCR_MOCK
切换到 JCR_JACKRABBIT
资源解析器类型的速度太快了。 JCR_MOCK
足以满足我的情况,如下所示:
- 从 class 路径 上的 JSON 文件加载内容
- 针对模拟存储库执行测试 class 的方法(class 应该从存储库中读取一些内容并将更多内容存储到其中)
- 读取被测者写的内容class并断言是否符合预期值
数据实际写入内存存储库。我无法阅读它是我自己的错误导致的,而不是使用的实现。
正在将 JSON 加载到 JCR_JACKRABBIT-backed AemContext
我设法按照
我在 setUp 方法中添加了以下几行:
Session session = aemContext.resourceResolver().adaptTo(Session.class);
RepositoryUtil.registerNodeType(session, getClass().getResourceAsStream("/nodetypes/types.cnd"));
就在aemContext.load().json("/jcrdata/myPage.json", "/etc/mystuff/myTool");
types.cnd
是我的 class 路径上的一个文件,其中包含在我的 AEM 实例上的 CRX 存储库中找到的节点类型定义。
这让我摆脱了 NPE,但由于某些原因,cq:Page
和 cq:PageContent
节点类型无法识别。这会导致 PersistenceException
在调用 aemContext.load().json("/jcrdata/myPage.json", "/etc/mystuff/myTool");
时抛出,如果这些类型中的任何一个节点存在于加载的 JSON 中。
问题似乎是 cq:Page
和 cq:PageContent
节点类型仍然找不到,尽管我已明确将它们添加到我的 types.cnd
文件中。我从 docs.adobe.com 中获取了这两种类型的定义,并确保包含这些定义中使用的名称空间前缀。
这是我的内容 cq:Page 中出现的堆栈跟踪示例 JSON:
java.lang.RuntimeException: org.apache.sling.api.resource.PersistenceException: Unable to create node at /etc/foo/bar/baz
at org.apache.sling.testing.mock.sling.loader.ContentLoader.json(ContentLoader.java:167)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.json(ContentLoader.java:120)
at com.foo.bar.baz.MyClassTest.setUp(MyClassTest.java:42)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.rules.ExternalResource.evaluate(ExternalResource.java:48)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:271)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:70)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner.run(ParentRunner.java:238)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:63)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
at org.junit.runners.ParentRunner.access[=11=]0(ParentRunner.java:53)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:229)
at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37)
at org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.apache.sling.api.resource.PersistenceException: Unable to create node at /etc/foo/bar/baz
at org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProvider.create(JcrResourceProvider.java:473)
at org.apache.sling.resourceresolver.impl.tree.ResourceProviderEntry.create(ResourceProviderEntry.java:479)
at org.apache.sling.resourceresolver.impl.ResourceResolverImpl.create(ResourceResolverImpl.java:1053)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.createResource(ContentLoader.java:217)
at org.apache.sling.testing.mock.sling.loader.ContentLoader.json(ContentLoader.java:163)
... 30 more
Caused by: javax.jcr.nodetype.NoSuchNodeTypeException: {http://www.day.com/jcr/cq/1.0}Page
at org.apache.jackrabbit.core.nodetype.NodeTypeRegistry.getEffectiveNodeType(NodeTypeRegistry.java:1024)
at org.apache.jackrabbit.core.nodetype.NodeTypeRegistry.getEffectiveNodeType(NodeTypeRegistry.java:487)
at org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl.getNodeType(NodeTypeManagerImpl.java:177)
at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1240)
at org.apache.jackrabbit.core.session.AddNodeOperation.perform(AddNodeOperation.java:111)
at org.apache.jackrabbit.core.session.AddNodeOperation.perform(AddNodeOperation.java:37)
at org.apache.jackrabbit.core.session.SessionState.perform(SessionState.java:200)
at org.apache.jackrabbit.core.ItemImpl.perform(ItemImpl.java:91)
at org.apache.jackrabbit.core.NodeImpl.addNodeWithUuid(NodeImpl.java:1769)
at org.apache.jackrabbit.core.NodeImpl.addNode(NodeImpl.java:1729)
at org.apache.sling.jcr.resource.internal.helper.jcr.JcrResourceProvider.create(JcrResourceProvider.java:435)
... 34 more
但是,只要将所有 cq:Page
和 cq:PageContent
类型替换为 nt:unstructured
,我就可以成功导入内容
这允许我针对存储库执行我的代码并读取我测试的 class 写在那里的内容,但我有点担心我的测试内容具有与其真实对应的节点类型不同的事实可能会影响测试结果在某些情况下。
JCR_JACKRABBIT
还需要创建一个 Derby 数据库,它不会在测试执行之间被清除。
总而言之,JCR_JACKRABBIT
引入了一些问题,并且在我的具体情况下与 JCR_MOCK
相比没有任何优势。建议我不要使用它,除非我真的需要模拟 JCR_MOCK
不支持的高级功能,例如事件或版本控制。
引用Stefan Seifert's comment on the wcm.io Developers mailing group
use JCR_JACKRABBIT only if you need special features not supported by JCR_MOCK, e.g. eventing, versioning etc. but only then, it’s the most heavyweight and most inperformant choice and not used much currently. we did some small improvements on this integration in the current trunk of sling-mock-jackrabbit in sling, esp. concering the content loader and special properties that cannot be imported, but this is not released yet.