使用jmockit,如何避免两种情况之间的影响?

时间:2015-07-07 01:36:39

标签: unit-testing jmockit

我有两个班,第一个班:

public class FirstClass {
    private static final Logger LOG = Logger.getLogger(FirstClass.class);

    public void action(){
        LOG.info("FirstClass.action.");
    }
}

第二课:

public class SecondClass {
    private static final Logger LOG = Logger.getLogger(SecondClass.class);

    public void action(){
        FirstClass firstClass = new FirstClass();
        firstClass.action();
    }
}

我将为这两个类编写单元测试,即第一类单元测试:

public class FirstClassTest {
    @Test
    public void testAction(){
        FirstClass firstClass = new FirstClass();
        firstClass.action();
    }
}

第二类单元测试:

public class SecondClassTest {
    @Mocked
    private Logger LOG;

    @Mocked
    private FirstClass firstClass;

    @Test
    public void testAction(){
        SecondClass secondClass = new SecondClass();
        secondClass.action();
    }
}  

关于第二类单元测试,由于第二类依赖于第一类,所以我嘲笑了第一个类,同时我也嘲笑了Logger类。

我添加了一个套件类来运行这两个类:

@RunWith(Suite.class)
@Suite.SuiteClasses({SecondClassTest.class ,FirstClassTest.class})
public class TestAll {
}

当我运行这个套件类时,它抛出以下异常:

java.lang.NullPointerException
at org.apache.log4j.Category.info(Category.java:663)
at steve.test.jmockit.issues.mocklog4j.FirstClass.action(FirstClass.java:12)
at steve.test.jmockit.issues.mocklog4j.FirstClassTest.testAction(FirstClassTest.java:12)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)

从此跟踪日志中,已经模拟了第一类的LOG。但实际上我并没有在FirstClassTest类中模拟Logger。

但是当我改变这个套件类时,首先运行FirstClassTest.class,然后运行SecondClassTest.class。所有案例都是成功的。

@RunWith(Suite.class)
@Suite.SuiteClasses({FirstClassTest.class ,SecondClassTest.class})
public class TestAll {
}

如何解决此问题并确保两种情况之间没有影响?谢谢!

2 个答案:

答案 0 :(得分:1)

发生异常是因为两个测试都在相同的 LOG.info(...)实例上调用LOG,这是未初始化的实例(即实例)及其所有参考字段null)。

LOG持有未初始化实例的原因是Logger类在执行第一个测试时被模拟。在第二次测试运行之前,类会被取消模拟,但这不会更改LOG对象的状态。因此,当第二次调用LOG.info(...)时,它不会被模拟,而是尝试使用仍然Logger的{​​{1}}字段,从而导致NPE。

避免此问题的方法是确保在null类被模拟之前初始化LOG字段。例如,可以通过添加Logger实例化@BeforeClass的方法(因为它包含有问题的FirstClass字段)来完成此操作。

答案 1 :(得分:0)

我运行了第一个套件,但没有看到您描述的问题。我的输出是:

Jul 09, 2015 12:00:59 AM First action
INFO: FirstClass.action.

我正在使用JMockit 1.18; JDK 1.8; JUnit 4.12