【问题标题】:Jmockit: Verify call method of interface fieldJmockit:验证接口字段的调用方法
【发布时间】:2023-04-04 03:21:01
【问题描述】:

使用的 JMockit 版本:1.21 我有这样的界面。 测试接口:

public interface TestInterface {
    boolean callMethod();
}

TestClass 有字段是该接口的一个实例 测试类:

public class TestClass {
    private final TestInterface inner = new TestInterface() {
        @Override
        public boolean callMethod() {
            subMethod();
            return false;
        }
    };
        public void subMethod() { System.out.println("Sub method");
    };
}

我尝试在本教程中通过伪造接口来验证调用方法。 http://jmockit.org/tutorial/Faking.html#interfacesd

测试方法。

public class TestInterfaceTest {
    TestClass sut;
    @Before
    public void setUp() {
        sut = Deencapsulation.newInstance(TestClass.class);
    }
    @Test
    public void mockAllClassesImplementingAnInterface() {

        TestInterface testInterface = new MockUp<TestInterface>() {
            @Mock
            public boolean callMethod(Invocation inv) {
                inv.proceed(); // throw exception here -> Will my expected method  be called here?
                return true;
            }
        }.getMockInstance();

        Deencapsulation.setField(sut, "INTER", testInterface);

        new NonStrictExpectations() {
            {
                Deencapsulation.invoke(sut, "subMethod");
            }
        };

        Boolean result = Deencapsulation.invoke(Deencapsulation.getField(sut, "INTER"), "callMethod");

        assertTrue(result);

        new Verifications() {
            {
                Deencapsulation.invoke(sut, "subMethod"); times = 1;
            }
        };
    }
}

java.lang.IllegalArgumentException:没有名称的类 找到“android.examples.helloandroid.$Impl_TestInterface”

如果你们不介意,请告诉我如何解决这个问题。非常感谢。

【问题讨论】:

  • 一旦我修复了您的“示例代码”中的错误(确保您的 MCVE 编译并运行!),一切正常,我没有看到这个错误.您必须详细说明您的问题。
  • 感谢@dcsohl 的确认。当前,我在 1.21 版上实现,它会抛出该错误。不仅是 1.21 版,而且 1.29 版也会引发该异常。 :D 你用什么版本来重现我的错误?
  • 我在 Android Studio 上测试:D

标签: java unit-testing junit jmockit


【解决方案1】:

在我对这个问题的重新评估中,您的问题似乎在于inv.proceed() 行。您不能在接口的Mockup 中包含该行。

Invocation.proceed() 用于当您希望 MockUp 实现进入实际代码时。但是因为你在模拟一个界面,没有真正的代码。您可能认为这是因为您的TestClass 实现具有接口的匿名实现,但MockUp 对那个匿名类一无所知;它正在模拟接口而不是您的匿名实现。

如果你去掉那条线,调用Invocation.proceed(),我想你会发现你的错误消失了。

【讨论】:

  • 感谢您的帮助。所以我们不知道验证匿名方法?
  • 我没这么说。我说你不能继续下去。不过,您可以模拟它并验证它是否被调用。
  • 我的意思是我们无法处理到该类并验证 subMehod 是否在实际方法中被调用。那正确吗?非常感谢您的支持。
  • 这完全取决于您真正想要测试什么。您无法模拟匿名类或实际测试它是否被调用......但您可以很容易地验证它是否按预期进行。在这种情况下,您可以验证 subMethod() 是否被调用。你必须用partial mockingsut 来做这件事,你应该质疑你是否真的想这样做,但你绝对可以。
  • 非常感谢。我没想到会这么简单。我经常使用 sut 的部分 mocking 来验证。你救了我的命。再次感谢你。我将在下面描述适合我的代码。
【解决方案2】:

基于@dcsohl 的指导。下面的代码对我有用。

    @Test
    public void mockAllClassesImplementingAnInterface() {
        // Partial mocking
        new NonStrictExpectations(sut) {
            {
                sut.subMethod();
            }
        };

        // Actual invocation
        Deencapsulation.invoke(Deencapsulation.getField(sut, "inner"), "callMethod");
        // Verify
        new Verifications() {
            {
                Deencapsulation.invoke(sut, "subMethod");
                times = 1;
            }
        };
    }

【讨论】:

  • 恐怕这个测试充满了错误(不应该使用Deencapsulation.invoke,一)。但更重要的是,整个事情(测试+要测试的代码)似乎毫无意义......一个适当的测试应该验证一些有意义的和外部可观察的行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多