在 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 快速注销服务的方法?

谢谢!

根据您的评论我更新了答案:

  1. 那就做2个测试方法吧。上下文对象在每次测试方法前重新初始化

  2. 注册服务的正确顺序很重要。使用 registerService 注册所有 Mock 服务(例如使用 Mockito 创建)。然后对应该成为 JUnit 测试一部分的所有服务使用 registerInjectActivateService。因为对于 registerInjectActivateService 所有引用的服务必须之前已经注册。

  3. 您不需要模拟 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());
    }
}

旧答案

  1. 您应该不注销 OSGi-Mocks(Sling-Mocks、AEM-Mocks)中的服务。你为什么需要这个?单元测试应该测试您的功能代码——而不是 OSGi 接线是否正常工作。只是接受你无法验证单元测试中的所有内容,即使是像非启动包这样的简单事情。因此你有健康检查。

  2. 如果你真的、真的需要这个!您可以扩展测试框架。它是 开源 。也许其他人也可以使用它。

  3. 或者查看基于 Pax Exam 的单元测试。在我看来,对于 "normal" AEM 项目来说,它有点过大了。但它提供了一个真正的 OSGi 容器。最大的优势是,它仍然可以 运行 作为 Maven 构建的正常部分。在 AEM 项目中,我看到对技术感兴趣的人经常引入此类测试。但实际上这些测试仅证明您可以在单元测试中拥有真正的 OSGi 容器。普通开发者不会接触这样的测试,感觉太复杂了。

  4. 最后看看服务器端 JUnit 测试。问题是,您在构建期间需要一个 AEM 实例和托管测试数据。代码覆盖率等指标也很难衡量。但无论如何,如果您有严重依赖 AEM 功能的测试,我还是会推荐这个。模拟 LiveRelationshipManager 的 50 行测试通常毫无价值。然后更好 [=7​​8=] 他们在服务器端使用真正的 AEM。 AEM 项目原型 也已经提供了集成测试(= 服务器端 JUnit 测试)。但即使在那里你也必须 start/stop 服务,用于测试什么?

https://sling.apache.org/documentation/tutorials-how-tos/testing-sling-based-applications.html

https://github.com/adobe/aem-project-archetype