我想使用JMockit模拟以下类:
public class A {
private int n;
public A(int n) {
this.n = n;
}
public boolean isCorrect() {
return n % 2 == 0;
}
}
该类在我的代码中初始化,我通常无法访问测试中的那部分代码。
在我的一些测试中,我想模拟它,以便如果类的值初始化为3,'isCorrect'将返回true(这不是正常行为),并且在其他一些测试中我想要模拟它以便无论如何初始化,'isCorrect'都将返回false。
我试图在文档中找到一种方法,但它不是那么用户友好,我放弃了它。
答案 0 :(得分:5)
对于你的第一个案例,你可以这样做:
new MockUp<A> () {
private int n;
@Mock public void $init(int n) { this.n = n; }
@Mock public boolean isCorrect() { return n == 3; }
};
对于你的第二个例子:
new MockUp<A> () {
@Mock public boolean isCorrect() { return false; }
};
例如,这会打印false,true,false,false:
new MockUp<A> () {
private int n;
@Mock public void $init(int n) { this.n = n; }
@Mock public boolean isCorrect() { return n == 3; }
};
System.out.println(new A(2).isCorrect());
System.out.println(new A(3).isCorrect());
new MockUp<A> () {
@Mock public boolean isCorrect() { return false; }
};
System.out.println(new A(2).isCorrect());
System.out.println(new A(3).isCorrect());
修改
根据你的评论,只为某些n值模拟类的一种方法是使用反射来检查字段的值:
new MockUp<A> () {
@Mock public boolean isCorrect(Invocation invocation) {
// Gets the invoked instance.
A a = invocation.getInvokedInstance();
int n = Deencapsulation.getField(a, "n");
if (n == 3) return true;
else return a.isCorrect();
}
};
但它变得有点脆弱,因为它取决于你A类中变量的名称。
一个更好的替代方案是在A类int getN() { return n; }
中为测试目的提供一个受包保护的getter,你不再需要反射了。
答案 1 :(得分:-3)
谢谢@assylias的回答。我想我找到了一种更好的方法来实现第一个模拟,它结合了你的第一个和第二个(编辑后)答案的想法。它是这样的:
new MockUp<A> () {
private int n;
@Mock
public void $init(Invocation inv, int n) {
this.n = n;
inv.proceed();
}
@Mock
public boolean isCorrect(Invocation inv) {
if (n == 3) {
return true;
}
return inv.proceed();
}
};
<强>更新强>
对于第二个模拟(粗暴的假返回),这将做:
new MockUp<A> () {
@Mock
public boolean isCorrect() {
return false;
}
};
再次感谢@assylias帮助我:)