java - 用于断言实现的表达式的字符串表示

标签 java android assert

由于 Java 的 assert 关键字是 fundamentally broken在 Android 上,我将要实现一个断言类,该类也可以配置为检查发布版本中的断言。

现在我可以做类似的事情:

MyAssertion.assert(a != 2)

当表达式为假时抛出 AssertionException。但是我怎样才能得到表达式的字符串表示形式以传递给错误消息呢?

最佳答案

唯一的方法是在 assert 方法中添加一个字符串参数:

MyAssertion.assert(a != 2, "a must not be equal to 2");

你得到的 assert 的输入要么是真要么是假,所以你不能从中构建一个有代表性的字符串。

否则,您可以像这样实现 assert:

MyAssertion.assertNotEquals(a, 2);

当失败时,您知道这是因为您测试的值等于 2,并且您可以构建一条信息性消息(尽管您不知 Prop 体等于 2 的是什么)。


如果你想以某种方式能够从一个断言中构建一个有意义的消息,我认为唯一可能的方法是构建一个字符串表达式,让 JavaScript 引擎对其求值并在表达式求值为 false 时构建一条消息.请注意,这会降低很多性能,因为启动 JavaScript 引擎需要很长时间。这可以通过在生产中禁用断言的机制来解决。

下面是一个例子。请注意,我使用的是新的 Java 8 Nashorn JavaScript 引擎,但这应该适用于旧版 Rhino。

使用示例:

int value = 3;
String str = "test";
Assertions.assertTrue("$1 == 3", value);
Assertions.assertTrue("$1 == 3 && $2 == 'test'", value, str);
Assertions.assertTrue("$1 == 4 && $2 == 'test'", value, str);

这将抛出第三个断言:

An assertion has failed: 3 == 4 && 'test' == 'test'

这个想法是您可以编写任何可以计算为 boolean 值的 JavaScript 友好表达式。占位符 $i 将替换为方法的参数($1 将替换为第一个参数,等等)。

这是类(class)。它可以改进(处理错误情况,例如参数不足等),但这应该足以让您入门。

public final class Assertions {

    private static final ScriptEngine ENGINE = new ScriptEngineManager().getEngineByName("nashorn");

    private Assertions() { }

    public static void assertTrue(String expression, Object... values) {
        for (int i = 0; i < values.length; i++) {
            ENGINE.put("$" + (i+1), values[i]);
        }
        try {
            boolean pass = (Boolean) ENGINE.eval(expression);
            if (!pass) {
                for (int i = 0; i < values.length; i++) {
                    expression = expression.replace("$" + (i+1), stringRepresentation(values[i]));
                }
                throw new AssertionError("An assertion has failed: " + expression);
            }
        } catch (ScriptException e) {
            throw new InternalError(e);
        } finally {
            for (int i = 0; i < values.length; i++) {
                ENGINE.getBindings(ScriptContext.ENGINE_SCOPE).remove("$" + (i+1));
            }
        }
    }

    private static String stringRepresentation(Object o) {
        if (o instanceof String) {
            return "'" + o + "'";
        }
        return o.toString();
    }

}

关于java - 用于断言实现的表达式的字符串表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32756683/

相关文章:

警告对话框中的 JavaFX 默认聚焦按钮

Android 偷偷解锁拍照

unit-testing - 单元测试中的多个断言

c++ - 在 "assert"(C++) 中使用 switch 语句

java - 根据元素的几个类别对大列表进行排序或分离

java - 使用循环添加具有随机变量的对象

java - 比较一个 ArrayList 并组合共同的元素

java - 从 RecyclerView 中的 EditText 获取 EditableText

java - 使用相机时 Android 中的权限被拒绝

python - Python断言的使用场景有哪些