在 wcm.io 的 AEM Mocks 中注销服务
Unregister a service in wcm.io's AEM Mocks
我正在遵循 wcm.io 提供的关于正确使用 AEM Mocks. Specifically, I am interested in unregistering a service. The documentation provides useful code for registering a service but nothing for unregistering. I have already looked at this similar question by 的指南,但针对他的问题的解决方案在 AEM Context 的情况下不起作用。
首先,如果我尝试这样注册服务:
ServiceReference ref = aemcontext.bundleContext().getServiceReference(MyServiceClass.class.getName());
它在 bundleContext
中注册但未在 aemcontext
中注册。 ref
对象确实已设置,但 aemcontext
从未真正拥有该服务,如果我尝试注册一个使用该服务的 servlet:
context.registerInjectActivateService(new MyServlet(), myParams);
此调用失败,因为 MyServlet
引用了 MyServiceClass
。有效的方法是直接在 aemcontext
上注册服务,例如:
aemcontext.registerService(MyServiceClass.class, new MyServiceClass());
但是,当我随后尝试按照 的问题提供的解决方案取消注册此服务时,这两个解决方案均无效。我没有收到错误,我想 ServiceRegistration<MyServiceClass> reg
确实发生了某些事情,但该服务从未从 aemcontext
中取消注册。如果我之后尝试使用上面的第二个命令再次注册它,我会收到一条错误消息:
Multiple matches found for unary reference 'myServiceClass' for class...
谁能帮帮我?有没有通过 AEM Mocks 快速注销服务的方法?
谢谢!
根据您的评论我更新了答案:
那就做2个测试方法吧。上下文对象在每次测试方法前重新初始化
注册服务的正确顺序很重要。使用 registerService
注册所有 Mock 服务(例如使用 Mockito 创建)。然后对应该成为 JUnit 测试一部分的所有服务使用 registerInjectActivateService
。因为对于 registerInjectActivateService
所有引用的服务必须之前已经注册。
您不需要模拟 SlingSettingsService。此服务已经是 Sling Mocks 的一部分 - 并且也支持更改 运行-模式。
这是一个 OSGi 服务示例:
@Component(service = FakeService.class)
public class FakeService {
@Reference
private SlingSettingsService slingSettingsService;
public boolean isAuthor() {
return slingSettingsService.getRunModes().contains("author");
}
public boolean isPublish() {
return slingSettingsService.getRunModes().contains("publish");
}
}
这是此服务的 JUnit 测试:
public class FakeTest {
@Rule
public final AemContext aemcontext = new AemContext();
private FakeService fakeService;
@Before
public void setup() {
fakeService = aemcontext.registerInjectActivateService(new FakeService());
}
@Test
public void testOnAuthor() {
aemcontext.runMode("author");
assertTrue(fakeService.isAuthor());
assertFalse(fakeService.isPublish());
}
@Test
public void testOnPublish() {
aemcontext.runMode("publish");
assertFalse(fakeService.isAuthor());
assertTrue(fakeService.isPublish());
}
}
旧答案
您应该不注销 OSGi-Mocks(Sling-Mocks、AEM-Mocks)中的服务。你为什么需要这个?单元测试应该测试您的功能代码——而不是 OSGi 接线是否正常工作。只是接受你无法验证单元测试中的所有内容,即使是像非启动包这样的简单事情。因此你有健康检查。
如果你真的、真的需要这个!您可以扩展测试框架。它是 开源 。也许其他人也可以使用它。
或者查看基于 Pax Exam 的单元测试。在我看来,对于 "normal" AEM 项目来说,它有点过大了。但它提供了一个真正的 OSGi 容器。最大的优势是,它仍然可以 运行 作为 Maven 构建的正常部分。在 AEM 项目中,我看到对技术感兴趣的人经常引入此类测试。但实际上这些测试仅证明您可以在单元测试中拥有真正的 OSGi 容器。普通开发者不会接触这样的测试,感觉太复杂了。
最后看看服务器端 JUnit 测试。问题是,您在构建期间需要一个 AEM 实例和托管测试数据。代码覆盖率等指标也很难衡量。但无论如何,如果您有严重依赖 AEM 功能的测试,我还是会推荐这个。模拟 LiveRelationshipManager 的 50 行测试通常毫无价值。然后更好 [=78=] 他们在服务器端使用真正的 AEM。 AEM 项目原型 也已经提供了集成测试(= 服务器端 JUnit 测试)。但即使在那里你也必须 start/stop 服务,用于测试什么?
https://sling.apache.org/documentation/tutorials-how-tos/testing-sling-based-applications.html
我正在遵循 wcm.io 提供的关于正确使用 AEM Mocks. Specifically, I am interested in unregistering a service. The documentation provides useful code for registering a service but nothing for unregistering. I have already looked at this similar question by
首先,如果我尝试这样注册服务:
ServiceReference ref = aemcontext.bundleContext().getServiceReference(MyServiceClass.class.getName());
它在 bundleContext
中注册但未在 aemcontext
中注册。 ref
对象确实已设置,但 aemcontext
从未真正拥有该服务,如果我尝试注册一个使用该服务的 servlet:
context.registerInjectActivateService(new MyServlet(), myParams);
此调用失败,因为 MyServlet
引用了 MyServiceClass
。有效的方法是直接在 aemcontext
上注册服务,例如:
aemcontext.registerService(MyServiceClass.class, new MyServiceClass());
但是,当我随后尝试按照 ServiceRegistration<MyServiceClass> reg
确实发生了某些事情,但该服务从未从 aemcontext
中取消注册。如果我之后尝试使用上面的第二个命令再次注册它,我会收到一条错误消息:
Multiple matches found for unary reference 'myServiceClass' for class...
谁能帮帮我?有没有通过 AEM Mocks 快速注销服务的方法?
谢谢!
根据您的评论我更新了答案:
那就做2个测试方法吧。上下文对象在每次测试方法前重新初始化
注册服务的正确顺序很重要。使用
registerService
注册所有 Mock 服务(例如使用 Mockito 创建)。然后对应该成为 JUnit 测试一部分的所有服务使用registerInjectActivateService
。因为对于registerInjectActivateService
所有引用的服务必须之前已经注册。您不需要模拟 SlingSettingsService。此服务已经是 Sling Mocks 的一部分 - 并且也支持更改 运行-模式。
这是一个 OSGi 服务示例:
@Component(service = FakeService.class)
public class FakeService {
@Reference
private SlingSettingsService slingSettingsService;
public boolean isAuthor() {
return slingSettingsService.getRunModes().contains("author");
}
public boolean isPublish() {
return slingSettingsService.getRunModes().contains("publish");
}
}
这是此服务的 JUnit 测试:
public class FakeTest {
@Rule
public final AemContext aemcontext = new AemContext();
private FakeService fakeService;
@Before
public void setup() {
fakeService = aemcontext.registerInjectActivateService(new FakeService());
}
@Test
public void testOnAuthor() {
aemcontext.runMode("author");
assertTrue(fakeService.isAuthor());
assertFalse(fakeService.isPublish());
}
@Test
public void testOnPublish() {
aemcontext.runMode("publish");
assertFalse(fakeService.isAuthor());
assertTrue(fakeService.isPublish());
}
}
旧答案
您应该不注销 OSGi-Mocks(Sling-Mocks、AEM-Mocks)中的服务。你为什么需要这个?单元测试应该测试您的功能代码——而不是 OSGi 接线是否正常工作。只是接受你无法验证单元测试中的所有内容,即使是像非启动包这样的简单事情。因此你有健康检查。
如果你真的、真的需要这个!您可以扩展测试框架。它是 开源 。也许其他人也可以使用它。
或者查看基于 Pax Exam 的单元测试。在我看来,对于 "normal" AEM 项目来说,它有点过大了。但它提供了一个真正的 OSGi 容器。最大的优势是,它仍然可以 运行 作为 Maven 构建的正常部分。在 AEM 项目中,我看到对技术感兴趣的人经常引入此类测试。但实际上这些测试仅证明您可以在单元测试中拥有真正的 OSGi 容器。普通开发者不会接触这样的测试,感觉太复杂了。
最后看看服务器端 JUnit 测试。问题是,您在构建期间需要一个 AEM 实例和托管测试数据。代码覆盖率等指标也很难衡量。但无论如何,如果您有严重依赖 AEM 功能的测试,我还是会推荐这个。模拟 LiveRelationshipManager 的 50 行测试通常毫无价值。然后更好 [=78=] 他们在服务器端使用真正的 AEM。 AEM 项目原型 也已经提供了集成测试(= 服务器端 JUnit 测试)。但即使在那里你也必须 start/stop 服务,用于测试什么?
https://sling.apache.org/documentation/tutorials-how-tos/testing-sling-based-applications.html