注意:问题末尾有一段完整的代码
我对一个类service
进行了JMockIt测试,该类具有两个依赖项(代码段中的factory
和consumer
)。服务在内部向工厂
依赖项请求类x
的对象,然后在此方法中将该对象传递给使用者
依赖项:
public void interactive(int i,E E){X v=f.create(i,E);c.consumer(v);}
在我的测试中,我希望使用service.interacter()
方法,并通过严格的期望假设使用者将接收一个满足特定属性的参数值。现在,由于x
类型的参数是一个不实现equals()的POJO,我想使用它提供的getter方法来执行检查;x
如下所示(完整代码段在问题末尾):
公共静态类X{private final int i;public final E E;//...请参阅下面的完整片段public int getI(){return i;}public E getE(){return E;}//E是枚举
因此,我所做的是尝试检查使用者是否接收到具有x.geti()==2
和x.gete()==e.b
的值,并且在我的期望块中使用具有(委托
:
new StrictExposities(){{consumer.Consumer(with ArgThat(new BaseMatcher(){//...//和new StrictExposities(){{consumer.Consumer(with(new Delegate(){//...
但是,这两个检查都失败,因为当它们调用
x.gete()
时,它们收到的东西不是枚举值e.b
。单元测试的输出是:
-----------------------------------------
RUNNING CHECKS ON: i=2, e=B
Direct reference match.
Reference through getter mismatch!
Ordinal through getter reference: 0
Identity hashcode from getter reference: 1282788025
Identity hashcode of expected reference: 519569038
-----------------------------------------
RUNNING CHECKS ON: i=2, e=B
Direct reference match.
Reference through getter mismatch!
Ordinal through getter reference: 0
Identity hashcode from getter reference: 1911728085
Identity hashcode of expected reference: 519569038
第一个问题是(这篇文章的标题):为什么JMockIt首先要介入这个getter?据我所知,我没有要求它模拟类X,因此对其getter方法的调用应该进入常规X字节码,但显然它没有;返回的枚举值的序数为零,这似乎是模拟的默认值。这种预期的行为是因为我错过了/误解了什么,还是可能是一个bug?
第二个问题是:假设jMockit的行为有一个有效的理由,我如何实现我想要的,并对只能通过X的getter方法获得的值执行这种检查?我如何修复这段代码来告诉JMockIt只需让类
x
单独工作。
这里是将编译和运行的完整代码段(也在http://pastebin.com/yrl7pdzv),我的类路径中有junit-4.12、hamcrest-core-1.3和jmockit-1.14,使用的是Oracle JDK 1.7.0_51。
package demonstrate;
import mockit.Delegate;
import mockit.Mocked;
import mockit.NonStrictExpectations;
import mockit.StrictExpectations;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.junit.Before;
import org.junit.Test;
public class SomeTest {
@Mocked
Factory factory;
@Mocked
Consumer consumer;
@Before
public void setUp() {
new NonStrictExpectations() {{
factory.create(anyInt, (E) any);
result = new Delegate() {
@SuppressWarnings("unused")
public X create(int i, E e) {
return new X(i, e);
}
};
}};
}
@Test
public void testWithMatcher() {
System.err.println("-----------------------------------------");
new StrictExpectations() {{
consumer.consume(withArgThat(new BaseMatcher() {
final int i = 2; final E e = E.B;
@Override
public boolean matches(Object item) {
return runChecks((X) item, i, e);
}
@Override
public void describeTo(Description description) {
description.appendText("\"i=" + i + ", e=" + e.name() + "\"");
}
}));
}};
new Service(factory, consumer).interact(2, E.B);
}
@Test
public void testWithDelegate() {
System.err.println("-----------------------------------------");
new StrictExpectations() {{
consumer.consume(with(new Delegate() {
@SuppressWarnings("unused")
public boolean check(X x) {
return runChecks(x, 2, E.B);
}
}));
}};
new Service(factory, consumer).interact(2, E.B);
}
private static boolean runChecks(X actual, int i, E e) {
System.err.println("RUNNING CHECKS ON: " + actual);
if (actual.getI() != i) {
System.err.println("Primitive int mismatch!");
return false;
}
if (actual.e == e) {
System.err.println("Direct reference match.");
} else {
System.err.println("Reference mismatch!");
return false;
}
E otherE = actual.getE();
if (otherE != e) {
System.err.println("Reference through getter mismatch!");
System.err.println("Ordinal through getter reference: "
+ otherE.ordinal());
System.err.println("Identity hashcode from getter reference: "
+ System.identityHashCode(otherE));
System.err.println("Identity hashcode of expected reference: "
+ System.identityHashCode(e));
return false;
}
return true;
}
public enum E {
A, B
}
public static class X {
private final int i;
public final E e;
public X(int i, E e) {
this.i = i;
this.e = e;
}
@Override
public String toString() {
return "i=" + i + ", e=" + e.name();
}
public int getI() {
return i;
}
public E getE() {
return e;
}
}
public static class Factory {
public X create(int i, E e) {
return new X(i, e);
}
}
public static class Consumer {
public void consume(X arg) {
}
}
public static class Service {
private final Factory f;
private final Consumer c;
public Service(Factory f, Consumer c) {
super();
this.f = f;
this.c = c;
}
public void interact(int i, E e) {
X v = f.create(i, e);
c.consume(v);
}
}
}
在jmockit-users列表中我被告知这实际上是一个bug。
建议的解决办法是使用@mocked(cascading=false)Factory;
,它确实使事情正常工作。
问题内容: 我在使用JMockit(1.21)模拟时遇到问题。请参阅以下内容,以简化我的实际课程。基本上我在我的代码中使用了某个地方,我希望对其进行模拟。 至于我的测试代码,此测试有效。 该测试失败。 我收到的错误消息: 我可以嘲笑像其他系统类和这样的,但只是似乎没有工作(也没有为此事)。我知道如何规避这是我的考验,所以我没有受到任何阻碍,但我不明白为什么不能嘲笑。删除Expectations块将
上面还有第二个问题。当我在Expects块中定义mock类时(如上),似乎只调用了构造函数,而不是,因此没有正确初始化对象。我通过将它移到方法中并在那里实例化该类来解决这个问题。看起来是这样的: 因此,这似乎得到了要调用的正确构造函数,但似乎还在调用。有什么见解吗?
我发现了一个很受欢迎的问题的答案,下面的代码是: 为什么...是必需的?如果我省略了,巴别就会对我抱怨说: 它看起来像扩展语法,但是一个布尔值。我找不到能解释到底发生了什么的医生。
在方法或类范围内,下面的行编译(带有警告): 在类作用域中,变量获取其默认值,以下给出未定义引用错误: 这难道不是第一个应该以相同的未定义引用错误结束吗?或者第二行应该编译?或者我错过了什么?
诚然,我对JMockit是新手,但出于某种原因,我在模仿System.getProperties()时遇到了麻烦。感谢以下帖子的帮助: https://stackoverflow.com/questions/25664270/how-can-i-partially-mock-the-system-class-with-jmockit-1-8?lq=1 我可以使用JMockit 1.12成功地模拟S