【问题标题】:JSF update managed bean with ServletContext listener for testingJSF 使用 ServletContext 侦听器更新托管 bean 以进行测试
【发布时间】:2017-05-12 21:16:05
【问题描述】:

在 JSF 2.2 应用程序中,我想构建一个用于使用 Selenium 进行测试的 war 文件。在那个 webtest.war 中,我想用一个名为 WebtestNodeCache 的模拟版本替换一个名为 NodeCache 的中心类,以将数据库和其他外部依赖项排除在测试之外。

NodeCache 是一个托管 bean:

@javax.faces.bean.ManagedBean(name = NodeCache.INSTANCE)
@javax.faces.bean.ApplicationScoped
public class NodeCache {
    public static final String INSTANE = "nodecache";
    // ...
}

为了潜入 WebtestNodeCache,我使用了这样的 ServletContextListener:

public class WebtestContextListener implements ServletContextListener {
     @Override
     public void contextInitialized(ServletContextEvent event) {
         WebtestNodeCache nodeCache = new WebtestNodeCache();
         ServletContext context = event.getServletContext();
         context.setAttribute(NodeCache.INSTANCE, nodeCache);
     }

     @Override
     public void contextDestroyed(ServletContextEvent sce) {}
}

在正常构建中,WebtestContextListener 和 WebtestNodeCache 被排除在 war 文件中,在测试构建中,它们被包括在内。

这似乎有效:当我登录时,我从 WebtestNodeCache 获取虚拟节点。

这是在应用程序上下文中替换 bean 的可靠方法还是我很幸运?

有没有更好的方法来偷偷测试假人?

【问题讨论】:

    标签: jsf mocking


    【解决方案1】:

    同时使用@ManagedBean 注释和监听器来替换对象不起作用。代码始终使用未模拟的生产代码托管 bean。

    用相同的名称定义一个新的@ManagedBean 是一个错误并且会阻止部署。

    我最终得到了这个:

    • 将同名的@ManagedBean注解放在真实的bean和它的mock上。

    • 构建时,只在构建 webtest.war 时包含 mock,而不是在常规构建中。

    • 在构建时,让构建脚本(在我的例子中是 Gradle)复制并过滤源代码,在生产代码中寻找 @ManagedBean 声明后面的特殊注释并取出这些行以删除 @987654325 @ 在生产代码上声明,以便只保留模拟中的代码。

    所以原来的 NodeCache 现在看起来像这样:

    @javax.faces.bean.ManagedBean(name = NodeCache.INSTANCE) // webtest:remove
    @javax.faces.bean.ApplicationScoped // webtest:remove
    public class NodeCache {
        public static final String INSTANE = "nodecache";
        // ...
    }
    

    和mocked版本有相同的注解,只是没有注释:

    @javax.faces.bean.ManagedBean(name = NodeCache.INSTANCE)
    @javax.faces.bean.ApplicationScoped
    public class WebtestNodeCache extends NodeCache {
        // ...
    }
    

    这里是 Gradle 构建脚本的相关部分:

    boolean isWebtest = false
    gradle.taskGraph.whenReady { taskGraph ->
        isWebtest = taskGraph.hasTask(compileWebtestWarJava);
    }
    
    task copySrc(type: Copy) {
        from "src"
        into "${buildDir}/src"
        outputs.upToDateWhen {
            // Always execute this task so that resources do or don't get filtered
            // when switching between normal war file and webtests.
            false
        }
        filter { String line ->
            isWebtest && line.contains("webtest:remove") ? null : line;
        }
    }
    

    这解决了我的问题。希望别人觉得它有用。

    【讨论】:

      猜你喜欢
      • 2013-01-06
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      • 1970-01-01
      • 1970-01-01
      • 2011-05-26
      • 2011-12-05
      • 2016-07-09
      相关资源
      最近更新 更多