gpt4 book ai didi

java - JMock "unexpected invocation"当相同的调用是 "expected once, never called"

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:31:07 27 4
gpt4 key购买 nike

我在代码中的某处更改了一些方法,这本不应该导致任何奇怪的测试失败,但 JMock 似乎不这么认为。

我把这个问题归结为最少量的废话,看起来像这样:

import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.lib.legacy.ClassImposteriser;
import org.junit.Test;

public class TestMocking {

@Test
public void test() {
Mockery mockery = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
final Owner owner = mockery.mock(Owner.class);
final RealThing thing = mockery.mock(RealThing.class, "thing");

mockery.checking(new Expectations() {{
oneOf(owner).getThing(); will(returnValue(thing));
oneOf(thing).method(); will(returnValue(Collections.emptyList()));
}});

owner.getThing().method();

mockery.assertIsSatisfied();
}

public static interface Owner {
BaseThing getThing();
}

public static interface BaseThing {
Collection<?> method();
}

public static interface RealThing extends BaseThing {
List<?> method();
}
}

(编辑:这现在使用了一个 ClassImposteriser,即使不再有类,因为我想证明你可以在没有那个冒名顶替者的情况下运行完全相同的代码并且测试将通过。)

运行结果:

unexpected invocation: thing.method()
expectations:
expected once, already invoked 1 time: owner.getThing(); returns <thing>
expected once, never invoked: thing.method(); returns <[]>
what happened before this:
owner.getThing()

好了,当从未调用预期的 thing.method() 时,“意外的”thing.method()。我以前曾在针对模拟对象测试多线程类时看到过这种情况,但这次它全部发生在单个线程中。就像 JMock 以某种方式从第一个方法调用返回一个不同的模拟对象,即使我没有模拟这样的对象。

如果我删除返回更具体类型的覆盖方法,那么它就会消失,但我显然不能那样做。同样,如果我删除 ClassImposteriser 的使用,问题就会消失,但我在实际测试中模拟的对象之一是其他人的类。我想我可以尝试在一个测试中使用两个 Mockery 实例,但除此之外我没有想法。

最佳答案

隐藏类(静态)方法与覆盖实例方法的工作方式并不完全相同。为了证明 JMock 不是这里的罪魁祸首,试试这个:

public class test3 {
public static void main(String[] args) {
Owner owner = new Owner();
owner.getThing().method(); //Like how you execute your test
RealThing thing = new RealThing();
thing.method(); //Similar to your mock.
}

private static class Owner {
private BaseThing thing = new RealThing();

public BaseThing getThing() {
return thing;
}
}

private static class BaseThing {
public static void method() {
System.out.println("Basething!");
}
}

private static class RealThing extends BaseThing {
public static void method() {
System.out.println("Realthing!");
}
}
}

请注意,对 method() 的两次调用打印不同的内容!两者都是 RealThing 的实例,但它们调用不同的方法。调用的静态方法取决于它是从子类调用还是从父类(super class)调用。在上面的第一个调用中,方法被声明为 BaseClass,因此调用了 BaseClass.method(),即使它是 RealClass 的实例。对 method() 的第二次调用被声明为 RealClass,因此调用了 RealClass.method()

因此,JMock 的结果是有效的。调用的 method() 与您设置的预期不同。

不要对我对此的解释感到满意。请务必在此处阅读:http://docs.oracle.com/javase/tutorial/java/IandI/override.html


修复(支持 BaseThing.method()),更改:

final RealThing thing = mockery.mock(RealThing.class, "thing");

收件人:

final BaseThing thing = mockery.mock(RealThing.class, "thing");

或者,如果您更喜欢使用 RealThing.method(),请更改:

owner.getThing().method()

收件人:

RealThing thing = (RealThing)owner.getThing();
thing.method();

关于java - JMock "unexpected invocation"当相同的调用是 "expected once, never called",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13850687/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com