JMockIt Mock 未使用 Faking 应用:Mocking parents of mocked 类

JMockIt Mock not being applied using Faking : Mocking parents of mocked classes

好的...我有一个答案...见下文。感谢所有提供帮助的人。我也更新了标题以更好地反映问题。


UPDATE2:正在使用空参数调用 ClassNotUnderTest(具有参数)的 parent class 的构造函数,后者又使用相同的空参数调用它的 parent ,最终导致空异常。

我试过:

模拟两个 parents,只有构造函数模拟并在尝试测试时使用其中一个或两个。 MockClassNotUnderTest 仍然调用真正的构造函数。

我尝试在测试方法的参数列表中使用 @Mocked 注释,因为我真的不想从那些 parents 返回任何东西......不。导致其他一些我不明白的错误。

我尝试在我的 $init 函数中调用 super(someParams),但无法编译。

HEEEEELLLLLPPPPP!!!!


更新:

好的,我的问题的根源不是如下所示的实现,而是模拟本身。当 MockClassNotUnderTest 调用它的构造函数时,它正在调用 ClassNotUnderTest 的真实 parent 的构造函数。我也试过嘲笑 ParentofClassNotUnderTest,但这只是导致了 NullPointerExceptions ......叹息。仍在搜索中,我会 post 及时更新。欢迎提出任何建议。


我是 JMockIt 的新手,但我的 Java 技能还不错。我正在尝试模拟被测 class 的依赖项 class。似乎正在调用真正的方法,或者它可能是超级 class (更有可能)。那么对我做错了什么有什么想法吗?

现在我知道有些人可能会评论我如何设置错误参数,以及如何应用等等,我欢迎评论,但主要问题是这段代码没有被模拟 properly/at 尽我所能。

预先回答几个问题...是的,我在这里搜索过,是的,我在 JMockIt 网站上查看了 tutorials/documentation...在我首先编写代码时都打开了。

我有几个类似的情况需要解决,所以非常感谢您的帮助。提前致谢。

像这样:

public ClassUnderTest {

    public someMethodUnderTest (){
        <blah blah setup stuff>
        try{
            somevar = new ClassNotUnderTest(someParamA, someParamB, someParamC);
        } catch(SomeExceptionA sea) {
            System.out.printline("Go boom");
        } <more catches here>
    }
}

我的test/mockclass如下(JUnit4/JMockIt):

public class TestClassUnderTest{

    ClassUnderTest cut;

    <Before method and constructor with some setup code for cut>

    @Test public void test_someMethodUnderTest(){
        MockClassNotUnderTest notUnderTest = new MockClassNotUnderTest();
        notUnderTest.error = 1;

        try{
            testResults = cut.someMethodUnderTest();
        } catch( SomeExceptionA sea) {
            <test that it went boom>
        }
    }

    public class MockClassNotUnderTest extends MockUp<ClassNotUnderTest> {

        public int error = 4;

        @Mock
        public void $init(someParamA, someParamB, someParamC) throws SomeExceptionA, SomeExceptionB, SomeExceptionC {

            if(error == 0) { thrown new SomeExeptionA(); }
            else if(error == 1) { thrown new SomeExeptionB(); }
            else if(error == 2) { thrown new SomeExeptionC(); }
            else { }
        }
    }
}

我的期望是您在测试方法中初始化的 new MockClassNotUnderTest() new ClassNotUnderTest() 共享状态您正在生产代码中进行初始化。

尝试将您的 error 设为 static 字段,以便在被伪造的对象之间共享。

我已经编写了一个示例测试用例,表明您在下面的评论是正确的。除非你 post 真正的代码,否则我无法复制你的问题...这是我的测试:

public class FakeTest {

    public static class Foo {
        public void doSomething() {
            try {
                Bar b = new Bar(73);
            } catch (Throwable t) {
                System.out.println("Got a " + t.getClass());
            }
        }
    }

    public static class Bar {
        private Integer param;
        public Bar(Integer parameter) {
            System.out.println("Got a real bar with param " + parameter); 
            this.param = parameter;
        }
    }

    public static class MockBar extends MockUp<Bar> {
        public int error = 4;

        @Mock
        public void $init(Integer parameter) {
            System.out.println("Initing fake with parameter " + parameter);
            if (error==1) {
                throw new IllegalAccessError();
            }
        }
    }

    @Test
    public void fakeTest() throws Exception {
        System.out.println("Testing...");
        MockBar mb = new MockBar();
        mb.error=1;

        Foo f = new Foo();
        f.doSomething();
    }
}

如您所料,输出是

Testing...
Initing fake with parameter 73
Got a class java.lang.IllegalAccessError

将此视为上述答案的第二部分。

那里提供的内容将成功地模拟出一个构造函数。我的问题的根源在于我原来的 MockClassNotUnderTest 正在调用 ClassNotUnderTest 的 REAL 父类的构造函数。伪造这并不是完全出乎意料的,所以我模拟了父对象......模拟从未调用过。

我最初的模拟设置(上面的 MockBar mb = new MockBar())会在其上方有一行来设置父模拟,它看起来完全一样,但名称不同。所以我可能有:

MockBarParent mbp = new MockBarParent();
MockBar mb = new MockBar();
mb.error = 1;

这显然行不通...这是行之有效的方法:

Mockit.setUpMock(new MockBarParent());
MockBar mb = new MockBar();
mb.error = 1;

至于为什么,我不确定,但我可以告诉你这是设置静态模拟的方式。

最后一句话。当您执行此操作时,这些模拟将保留在内存中。在离开测试函数之前一定要调用 Mockit.tearDownMocks() 否则它会持续到其他测试中。 JUnit 没有按顺序 运行 测试,所以这会导致各种有趣的错误。

再次感谢您的帮助!!!! @dcsohl 和尼古拉斯