当前位置: 首页 > 知识库问答 >
问题:

为什么JMockIt要模拟这个片段中类X的getter X.gete()?

太叔鹏云
2023-03-14

注意:问题末尾有一段完整的代码

我对一个类service进行了JMockIt测试,该类具有两个依赖项(代码段中的factoryconsumer)。服务在内部向工厂依赖项请求类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()==2x.gete()==e.b的值,并且在我的期望块中使用具有(委托 )和具有ArgThat(匹配器 )的 :

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);
        }
    }
}

共有1个答案

西门展
2023-03-14

在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