我正在Graal之上编写一个应用程序,该应用程序将能够执行不同语言的小脚本。
我正在尝试为用于将Context.eval()调用(类型:值)的结果转换/处理为Java对象的类编写一些单元测试。我从文档中知道Value实例始终绑定到Context,因此当我尝试编写如下内容时:
@Test
public void NumericFloatTest() throws ScriptExecutionException {
GuestLanguageResultProcessor LangProcessor = new GuestLanguageResultProcessor();
Float javaValue = (float) 43.25;
Value numValue = Value.asValue(javaValue);
LangProcessor.processResult(numValue);
Object result = LangProcessor.processResult(numValue);
assertThat(result.getClass()).isEqualTo(Float.class);
}
我收到以下错误:
java.lang.IllegalStateException: No current context is available. Make sure the Java method is invoked by a Graal guest language or a context is entered using Context.enter().
我想从概念上讲,没有关联的来宾代码就没有“ Value”实例是没有意义的,所以我的问题是:
如何测试我的GuestLanguageResultProcessor类?创建上下文时,我是否必须“膨胀”单元测试?
专家的附加问题:我也使用此类(GuestLanguageResultProcessor)从多语言Value实例中提取Java值,以便关闭上下文。换句话说,在我看来,在能够执行Context.close()之前,我需要调用[值实例] .asString()或.asWhatever()以便获得结果并能够关闭上下文而无需按照docs中的说明获取IllegalStateException。
我做对了吗?有没有更好的方法来处理结果并安全地关闭上下文?
谢谢!
答案 0 :(得分:4)
如何测试我的GuestLanguageResultProcessor类?我必须通过创建上下文来“膨胀”我的单元测试吗?
我担心有点胀气是必要的。我建议使用以下代码来进行测试。也可以在测试基类中完成此操作,以避免重复。
Context context;
@Before
public void setup() {
context = Context.create();
context.enter();
}
@After
public void setup() {
context.leave();
context.close();
}
@Test
public void NumericFloatTest() throws ScriptExecutionException {
GuestLanguageResultProcessor LangProcessor = new GuestLanguageResultProcessor();
Float javaValue = (float) 43.25;
Value numValue = Value.asValue(javaValue);
LangProcessor.processResult(numValue);
Object result = LangProcessor.processResult(numValue);
assertThat(result.getClass()).isEqualTo(Float.class);
}
我做对了吗?有没有更好的方法来处理结果并安全地关闭上下文?
值实例可以绑定到来宾语言对象,例如JavaScript对象,一旦上下文关闭,它们就无效。并非总是可能将来宾语言对象转换为永久Java表示形式。例如,polyglot值可能引用JavaScript对象的整个图。
如果可能的话,我建议保持上下文开放,只要需要值就可以,因为它不需要任何转换。
如果这是不可能的,并且您仅处理基元和数组,则可以尝试使用以下方法。您也可以尝试通过访问其成员将对象复制到Java Land。
Object copyToJavaLand(Value value) {
if (value.isBoolean()) {
return value.asBoolean();
} else if (value.isString()) {
return value.asString();
} else if (value.isNumber()) {
return value.as(Number.class);
} else if (value.isHostObject()) {
return value.asHostObject();
} else if (value.isProxyObject()) {
return value.asProxyObject();
} else if (value.hasArrayElements()) {
Object[] array = new Object[(int) value.getArraySize()];
for (int i = 0; i < array.length; i++) {
array[i] = copyToJavaLand(value.getArrayElement(i));
}
return array;
}
throw new IllegalArgumentException("Cannot copy value " + value + ".");
}
请注意,此方法并不总是安全的。例如,如果数组引用自身,则此方法将崩溃并出现堆栈溢出错误。