简体   繁体   English

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

[英]Using jmockit, how to avoid the impact between two cases?

I have two classes, the first class: 我有两节课,第一节课:

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

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

the second class: 第二类:

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

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

I will write unit test for these two classes, the first class unit test: 我将为这两个类编写单元测试,第一个类是单元测试:

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

the second class unit test: 第二类单元测试:

public class SecondClassTest {
    @Mocked
    private Logger LOG;

    @Mocked
    private FirstClass firstClass;

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

About the second class unit test, As the second class depend on the first class, so I mocked the first class, at same time I also mocked Logger class. 关于第二类单元测试,因为第二类依赖于第一类,所以我嘲笑了第一类,同时我也嘲笑了Logger类。

I add a suite class to run these two classes: 我添加了一个套件类来运行这两个类:

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

When I run this suite class, it throw the follow exception: 当我运行此套件类时,它将引发以下异常:

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)

From this trace log, the LOG of first class has been mocked. 从此跟踪日志中,已模拟了第一类的LOG。 but in fact I don't mock Logger in FirstClassTest class. 但实际上我不在FirstClassTest类中模拟Logger。

But when I changed this suite class, firstly run FirstClassTest.class, and then run SecondClassTest.class. 但是,当我更改此套件类时,首先运行FirstClassTest.class,然后运行SecondClassTest.class。 all cases are successful. 所有案例都是成功的。

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

How to fix this issue and ensure that there is no effect between the two cases? 如何解决此问题并确保这两种情况之间没有影响? Thanks! 谢谢!

The exception occurs because both tests call LOG.info(...) on the same LOG instance, with this being an uninitialized instance (ie, an instance with all of its reference fields null ). 发生异常是因为两个测试都在同一 LOG实例上调用LOG.info(...) ,而这是未初始化的实例(即,其所有引用字段为null的实例)。

The reason LOG holds an uninitialized instance is that the Logger class got mocked when the first test was executed. LOG包含未初始化实例的原因是,在执行第一个测试时会模拟Logger类。 The class gets unmocked before the second test runs, but that doesn't change the state of the LOG object. 在第二次测试运行之前,将对类进行模拟,但这不会更改LOG对象的状态。 So, when the second call to LOG.info(...) occurs, it is not mocked, but attempts to use Logger fields which are still null , causing the NPE. 因此,当第二次调用LOG.info(...)时,它不会被LOG.info(...) ,但是会尝试使用仍然为null Logger字段,从而导致NPE。

The way to avoid the problem is to ensure the LOG field gets initialized before the Logger class is mocked. 避免该问题的方法是确保在模拟Logger类之前初始化LOG字段。 This can be done, for example, by adding a @BeforeClass method which instantiates FirstClass (since it holds the LOG field in question). 例如,可以通过添加实例化FirstClass@BeforeClass方法来完成此操作(因为它保存有问题的LOG字段)。

I ran the first Suite and do not see the issue you describe. 我运行了第一个套件,但是看不到您描述的问题。 My output is: 我的输出是:

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

I'm using JMockit 1.18; 我正在使用JMockit 1.18; JDK 1.8; JDK 1.8; JUnit 4.12 JUnit 4.12

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM