如何静态测试EL表达式的正确性?

时间:2010-10-14 14:01:57

标签: testing jsf el

在我们的Web应用程序中,我们对Java bean进行了一些重构,由于这种重构,一些操作/获取器不再可用。例如,在以下示例中:

public class MyBean implements Serializable {

    // Old name
    // public String getFoo() { return "foo"; }

    // New name
    public String getBar() { return "bar"; }

}

如果我的JSF代码仍然如下:

<h:inputText value="#{myBean.foo}" .../>

然后会产生异常。

我主要担心的是,某些EL表达式现在可能指向Java bean上的未使用方法,而且当我浏览适当的页面时,我只能看到它。当EL表达式位于特定条件下呈现的部分和/或由Ajax重新呈现时,它变得更难。

所以我的问题是如何静态检查这些EL表达式的正确性?

我已经检查了JSFUnit工具,因为它提供了这样的工具。所以我尝试this example,但它似乎没有按预期工作。在一个简单的测试页面上,只有很少的EL表达式(一些是正确的,另一些是未出现的bean和/或方法的错误),测试成功,这是不正确的。

非常重要的一点:我的bean是在我的Spring配置中定义的,而{strong>不是在faces-config.xml中。

另请注意,我只需要检查EL表达式是否引用现有的bean和方法,而不一定是否正确执行此操作...

技术信息:

Java 1.6,Spring 2.5,JSF 1.2,EL Functor,Facelets和Richfaces 3.3

1 个答案:

答案 0 :(得分:1)

我找不到符合我要求的工具。所以我在我的应用程序上写了一个小bean。此bean将提供一个操作,该操作将读取目录并分析其中的每个.xhtml文件(并以递归方式执行此操作)。当然,我将不得不运行我的应用程序(因此分析并不是真正的静态),但这个解决方案的优点是我可以访问ELContextELExpressionFactory我真正使用的web-application,都链接到我的Spring上下文。

这是代码中有趣的部分:

// Analyse a XHTML file
private void analyzeXHTMLFile(File f) throws IOException {
    List<String> lines = FileUtils.readLines(f);
    for (String l : lines) {
        List<String> els = getEL(l);
        for (String el : els) {
            evaluateEL(el);
        }
    }
}

// Get a List of EL on the line.
private List<String> getEL(String line) {
    List<String> el = new ArrayList<String>();
    int i = line.indexOf("#{");
    if (i == -1) {
        return el;
    }
    while (i != -1) {
        int j = line.indexOf("}", i);
        if (j == -1) {
            return el;
        }
        el.add(line.substring(i, j + 1));
        i = line.indexOf("#{", i + 1);
    }
    return el;
}

// Evaluate the EL
private void evaluateEL(String el) {
    FacesContext context = FacesContext.getCurrentInstance();
    ELContext elContext = context.getELContext();
    ValueExpression ve = context.getApplication().getExpressionFactory().createValueExpression(elContext, el, Object.class);
    if (ve != null) {
        Object o = null;
        try {
            o = ve.getValue(elContext);
        } catch (PropertyNotFoundException pnfe) {
            // Handle this error
        }
        if (o == null) {
            // Handle another error
        }
    }
}