【问题标题】:ClassLoader throws NullPointerException when trying to partial mock a class with JMockit尝试使用 JMockit 部分模拟类时,ClassLoader 抛出 NullPointerException
【发布时间】:2011-11-10 20:45:29
【问题描述】:

使用 Eclipse 3.6.1
Java 1.6.0_26
JMockit 0.999.10

更新:我能够创建一个 SSCCE,我将其发布在下面:

UPDATE2:添加了 DaemonHelper。此外,如果我从构造函数中删除 DaemonHelper,我会得到一个 ClassCircularityError。相关吗?

当我从类加载器获取 NPE 时,我正在尝试对一个类进行部分模拟,同时模拟该类的多个依赖项。 NPE 调用堆栈如下所示

我有一个像这样的Daemon 类:

public class Daemon extends DaemonParent {

public Daemon(ConfigParent config, DaemonHelper helper) {
    super(config, helper);
}

@Override
public void execute() {
    log("Starting");
    if (config.test()) {
        log("Testing");
    }

    log("Ending");  
}
}

守护进程有这样的父级:

public abstract class DaemonParent extends Thread {

protected ConfigParent config;
protected DaemonHelper helper;

public DaemonParent(ConfigParent config, DaemonHelper helper) {
    this.config = config;
    this.helper = helper;
}


public abstract void execute();

public void log(String s) {
    System.out.println(s);
}
}

有一个辅助类,如:

public class DaemonHelper extends Thread {

}

配置看起来像:

public class ConfigParent {

protected ConfigHelper helper;

public ConfigParent(ConfigHelper helper) {
    this.helper = helper;
}

public boolean test() {
    return false;
}
}

Config Parent 看起来像:

public class ConfigParent implements Serializable {

protected ConfigHelper helper;

public ConfigParent(ConfigHelper helper) {
    this.helper = helper;
}

public boolean test() {
    return false;
}
}

测试看起来像:

public class DaemonTest {

@Test
public void testExecute(final ConfigHelper ch, final DaemonHelper dh) {
    final Config c = new Config(ch);
    final Daemon d = new Daemon(c, dh);

    new NonStrictExpectations(d) {
        {

        }
    };

    d.execute();

    new Verifications() {{
        d.log("Starting");
        d.log("Ending");
    }};
}
}

当我尝试运行此测试时,我收到以下错误。请注意,仅当 DaemonParent 和 Daemon Helper 将 java.lang.Thread 作为超类时才会弹出此错误:

java.lang.NullPointerException
at java.lang.Thread.interrupted(Unknown Source)
at sun.misc.Resource.getBytes(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$000(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.junit.internal.runners.model.EachTestNotifier.addFailure(EachTestNotifier.java:23)
at org.junit.runners.ParentRunner.run(ParentRunner.java:242)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

我尝试注释掉 NonStrictExpectations 块和 Verifications 块,我得到了同样的错误。

NPE 是从对 currentThread() 的调用中抛出的...我不知道它是如何失败的。

有什么想法吗?

【问题讨论】:

    标签: java unit-testing junit jmockit


    【解决方案1】:

    原来问题是Daemon的根超类是java.lang.Thread,导致JMockit出现问题。解决方案是静态部分模拟测试所需的方法。

    public class DaemonTest {
    
    @Test
    public void testExecute(final ConfigHelper ch, final DaemonHelper dh) {
    
    new NonStrictExpectations(d) {
        @Mocked({"log"}
        Daemon d;
        @Mocked({"()"})
        DaemonHelper dh;
        {
    
        }
    };
    
    
    final Config c = new Config(ch);
    final Daemon d = new Daemon(c, dh);
    d.execute();
    
    new Verifications() {{
        d.log("Starting");
        d.log("Ending");
    }};
    }
    }
    

    【讨论】:

    • 谢谢!我本来想写一个答案,但你打败了我。该测试完全模拟了Thread 类(dh 模拟参数)和部分模拟(在构造函数中传递d),这是应该避免的。另一种方法是dh 模拟任何东西,方法是用@Mocked("") 注释参数。 (无论如何,我在模拟 java.lang.Thread 类时改进了 JMockit 的健壮性,版本 0.999.12。)
    • @Rogerio:谢谢!我期待新版本。
    猜你喜欢
    • 1970-01-01
    • 2014-07-15
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多