【问题标题】:JMockit injecting nested member variablesJMockit 注入嵌套成员变量
【发布时间】:2018-09-23 08:25:54
【问题描述】:

我目前正在尝试测试我的代码的执行路径,但在涉及嵌套类成员变量时遇到了一些问题。考虑以下类结构:

System (System under test)
 -> ClassA
   -> ClassB
     -> ClassC

名为System 的类包含ClassA 的一个实例,并将调用其中一个方法。 ClassA 将同样包含 ClassB 的一个实例,并将调用其中一个方法等。

@RunWith(JMockit.class)
public class SomeTest {
    @Tested
    private System system;

    @Injectable
    private ClassA memberA;

    @Injectable
    private ClassB memberB;

    @Injectable
    private ClassC memberC;

    @Test
    public void doSystemTest() {
        // Do stuff
        system.handle();

        new Verifications() {
            {
                system.handle(); times = 1;
                memberA.doSomeAStuff(); times = 1;
                memberB.doSomeBStuff(); times = 1; // Results in test failure: 
            }
        };
    }
}

当我运行此测试时,我收到以下错误:

缺少 1 次调用: ca.kgli.jmockit.ClassB#doSomeBStuff() 在模拟实例上:ca.kgli.jmockit.ClassB@1a052a00

供参考,代码如下:

public class System {
    private ClassA memberA;

    public void handle() {
        memberA.doSomeAStuff();
    }
}

public class ClassA {
    private ClassB memberB;

    public void doSomeAStuff() {
        memberB.doSomeBStuff();
    }
}

public class ClassB {
    private ClassC member;

    public void doSomeBStuff() {
        member.stuffCSays("arsenic");
    }
}

public class ClassC {
    public String stuffCSays(String input) {
        return "Hello, " + input;
    }
}

所以我的问题是,为什么方法doSomeBStuff 没有被调用? JMockit 不应该以这种方式使用吗?我是这个测试工具包的新手,因此非常感谢任何关于这个问题的帮助或见解。

【问题讨论】:

  • memberA 作为模拟注入,这意味着它的所有方法都没有实现(除非使用结果和返回另外定义)所以 memberA 并没有真正调用 menberB,这在单元测试中是完全可以的。您应该将 System.java 上的测试限制为验证调用是否委派给 memberA。然后有一个 ClassA 测试来验证 memberB 正在被使用,等等
  • 谢谢!我想这证实了我一直以来的怀疑。似乎 JMockit 不是为这种方式设计的,这在单元测试的上下文中是有意义的。
  • 您正在寻找的是@Tested(fullyInitialized = true),它允许从调用System#doSystemTest() 开始测试所有类,无需模拟。见Getting started

标签: java unit-testing junit jmockit


【解决方案1】:

当你mockClassA时,doSomeAStuff()的真正实现被Jmockit拦截,所以它不会调用doSomeBStuff()

只应在对 System 执行单元测试时模拟 ClassA

@RunWith(JMockit.class)
public class SomeTest {
    @Tested
    private System1 system;

    @Injectable
    private ClassA memberA;

    @Test
    public void doSystemTest() {
        // Do stuff
        system.handle();

        new Verifications() {
            {
                memberA.doSomeAStuff(); times = 1;
            }
        };
    }
}

ClassB 的模拟应该只在您对 ClassA 执行单元测试时发生。

【讨论】:

    猜你喜欢
    • 2013-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-13
    • 1970-01-01
    • 2011-02-16
    • 2022-07-10
    • 2023-03-31
    相关资源
    最近更新 更多