java方法参数验证_java – 验证方法体中是否使用了方法参数

我有一个界面,如下所示

interface Evaluator {

boolean requiresP2();

EvalResult evaluate(Param1 p1, Param2 p2, Param3 p3);

// some more methods

}

该接口由几个类实现. CAL方法的参数p2由某些人使用,而其他人则不使用.方法requiresP2基本上返回一个布尔值,告诉evaluate方法是否使用p2.

现在,这些问题在上下文中可能看起来有点奇怪,但请相信我,这在我们的用例中是有意义的.另外,需要花费大量时间来重构所有代码以消除对requiresP2方法的需求,所以如果我们讨论除了自上而下的代码库重构之外的解决方案,我将不胜感激.

问题是方法requiresP2的返回值是基于evaluate方法的实现方式.因此,每个人都必须确保在更改evaluate方法时更新requiresP2方法.

我正在寻找方法,以便这可以由编译器/单元测试/ linters强制执行,而不是将它留给开发人员的内存.

编辑:我仍在探索模拟框架对此问题的适用性.

我认为我可以在单元测试中反映在单元测试中检查evaluate的主体以检查它是否引用p2然后确保它与requiresP2方法返回的值匹配但似乎无法检查方法身体使用反射.

我正在寻找关于如何做到这一点的建议.任何输入都表示赞赏.

解决方法:

您可以使用ASM来检查是否使用了该参数.

使用例如将其添加到项目中Apache Ivy,您可以将其添加到ivy.xml:

或者为Maven,Gradle等执行等效操作.然后,您可以通过以下方式检查参数:

import java.io.IOException;

import java.io.InputStream;

import java.io.UncheckedIOException;

import java.util.concurrent.atomic.AtomicBoolean;

import org.objectweb.asm.ClassReader;

import org.objectweb.asm.ClassVisitor;

import org.objectweb.asm.MethodVisitor;

import org.objectweb.asm.Opcodes;

// . . .

public static boolean usesP2(Evaluator evaluator) {

AtomicBoolean usesP2 = new AtomicBoolean(false);

String internalName = evaluator.getClass().getName().replace('.', '/');

String classFileResource = "/" + internalName + ".class";

ClassVisitor visitor = new ClassVisitor(Opcodes.ASM6) {

@Override

public MethodVisitor visitMethod(int access, String name,

String desc, String signature, String[] exceptions) {

if ("evaluate".equals(name)) {

return new MethodVisitor(Opcodes.ASM6) {

@Override

public void visitVarInsn(final int insn, final int slot) {

if (slot == 2) usesP2.set(true);

}

};

}

return super.visitMethod(access, name, desc, signature, exceptions);

}

};

try (InputStream is = Evaluator.class.getResourceAsStream(classFileResource)) {

ClassReader reader = new ClassReader(is);

reader.accept(visitor, 0);

} catch (IOException e) {

throw new UncheckedIOException(e);

}

return usesP2.get();

}

public static void assertCorrectlyDocumentsP2(Evaluator evaluator) {

boolean usesP2 = usesP2(evaluator);

if (usesP2 && !evaluator.requiresP2()) {

throw new AssertionError(evaluator.getClass().getName() +

" uses P2 without documenting it");

}

if (!usesP2 && evaluator.requiresP2()) {

throw new AssertionError(evaluator.getClass().getName() +

" says it uses P2 but does not");

}

}

单元测试:

@Test

public void testFalsePositive() {

assertCorrectlyDocumentsP2(new FalsePositive());

}

@Test

public static void testFalseNegative() {

assertCorrectlyDocumentsP2(new FalseNegative());

}

(这假设有两个错误的Evaluators,FalsePositive和FalseNegative,其中一个文档表示它使用P2但没有,另一个文档没有记录它使用P2,即使它分别.)

注意:在usesP2中,我们检查堆栈帧的插槽2中的变量指令(访问本地变量的指令).插槽编号为0,第一个是这个. P2仅在插槽2中,因为Evaluator :: evaluate是一种实例方法.如果它是静态方法,我们必须检查是否使用了插槽1以检测是否使用了参数P2.警告讲师.

标签:java,unit-testing,reflection,linter

来源: https://codeday.me/bug/20190724/1521536.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值